Fix wrongly unmangled macros for transmute_ptr_to_ptr and transmute_bytes_to_str (#16105)
Closes rust-lang/rust-clippy#16104 changelog: [`transmute_ptr_to_ptr`] fix wrongly unmangled macros [`transmute_bytes_to_str`] fix wrongly unmangled macros
This commit is contained in:
commit
45168a79cd
6 changed files with 111 additions and 58 deletions
|
|
@ -17,6 +17,8 @@ pub(super) fn check<'tcx>(
|
|||
arg: &'tcx Expr<'_>,
|
||||
msrv: Msrv,
|
||||
) -> bool {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let arg_sugg = sugg::Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut applicability);
|
||||
match (from_ty.kind(), to_ty.kind()) {
|
||||
(ty::RawPtr(from_pointee_ty, from_mutbl), ty::RawPtr(to_pointee_ty, to_mutbl)) => {
|
||||
span_lint_and_then(
|
||||
|
|
@ -25,40 +27,38 @@ pub(super) fn check<'tcx>(
|
|||
e.span,
|
||||
"transmute from a pointer to a pointer",
|
||||
|diag| {
|
||||
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
if from_mutbl == to_mutbl
|
||||
&& to_pointee_ty.is_sized(cx.tcx, cx.typing_env())
|
||||
&& msrv.meets(cx, msrvs::POINTER_CAST)
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
e.span,
|
||||
"use `pointer::cast` instead",
|
||||
format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_paren()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else if from_pointee_ty == to_pointee_ty
|
||||
&& let Some(method) = match (from_mutbl, to_mutbl) {
|
||||
(ty::Mutability::Not, ty::Mutability::Mut) => Some("cast_mut"),
|
||||
(ty::Mutability::Mut, ty::Mutability::Not) => Some("cast_const"),
|
||||
_ => None,
|
||||
}
|
||||
&& !from_pointee_ty.has_erased_regions()
|
||||
&& msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS)
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
e.span,
|
||||
format!("use `pointer::{method}` instead"),
|
||||
format!("{}.{method}()", arg.maybe_paren()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
diag.span_suggestion_verbose(
|
||||
e.span,
|
||||
"use an `as` cast instead",
|
||||
arg.as_ty(to_ty),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if from_mutbl == to_mutbl
|
||||
&& to_pointee_ty.is_sized(cx.tcx, cx.typing_env())
|
||||
&& msrv.meets(cx, msrvs::POINTER_CAST)
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
e.span,
|
||||
"use `pointer::cast` instead",
|
||||
format!("{}.cast::<{to_pointee_ty}>()", arg_sugg.maybe_paren()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else if from_pointee_ty == to_pointee_ty
|
||||
&& let Some(method) = match (from_mutbl, to_mutbl) {
|
||||
(ty::Mutability::Not, ty::Mutability::Mut) => Some("cast_mut"),
|
||||
(ty::Mutability::Mut, ty::Mutability::Not) => Some("cast_const"),
|
||||
_ => None,
|
||||
}
|
||||
&& !from_pointee_ty.has_erased_regions()
|
||||
&& msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS)
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
e.span,
|
||||
format!("use `pointer::{method}` instead"),
|
||||
format!("{}.{method}()", arg_sugg.maybe_paren()),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
diag.span_suggestion_verbose(
|
||||
e.span,
|
||||
"use an `as` cast instead",
|
||||
arg_sugg.as_ty(to_ty),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR};
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::{std_or_core, sugg};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, Mutability};
|
||||
|
|
@ -17,8 +16,7 @@ pub(super) fn check<'tcx>(
|
|||
arg: &'tcx Expr<'_>,
|
||||
const_context: bool,
|
||||
) -> bool {
|
||||
let mut triggered = false;
|
||||
|
||||
let arg_sugg = || sugg::Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut Applicability::Unspecified);
|
||||
if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (*from_ty.kind(), *to_ty.kind()) {
|
||||
if let ty::Slice(slice_ty) = *ty_from.kind()
|
||||
&& ty_to.is_str()
|
||||
|
|
@ -29,8 +27,6 @@ pub(super) fn check<'tcx>(
|
|||
|
||||
let postfix = if from_mutbl == Mutability::Mut { "_mut" } else { "" };
|
||||
|
||||
let snippet = snippet(cx, arg.span, "..");
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
TRANSMUTE_BYTES_TO_STR,
|
||||
|
|
@ -38,15 +34,17 @@ pub(super) fn check<'tcx>(
|
|||
format!("transmute from a `{from_ty}` to a `{to_ty}`"),
|
||||
"consider using",
|
||||
if const_context {
|
||||
format!("{top_crate}::str::from_utf8_unchecked{postfix}({snippet})")
|
||||
format!("{top_crate}::str::from_utf8_unchecked{postfix}({})", arg_sugg())
|
||||
} else {
|
||||
format!("{top_crate}::str::from_utf8{postfix}({snippet}).unwrap()")
|
||||
format!("{top_crate}::str::from_utf8{postfix}({}).unwrap()", arg_sugg())
|
||||
},
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
triggered = true;
|
||||
} else if (cx.tcx.erase_and_anonymize_regions(from_ty) != cx.tcx.erase_and_anonymize_regions(to_ty))
|
||||
&& !const_context
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cx.tcx.erase_and_anonymize_regions(from_ty) != cx.tcx.erase_and_anonymize_regions(to_ty)) && !const_context
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
|
|
@ -54,23 +52,21 @@ pub(super) fn check<'tcx>(
|
|||
e.span,
|
||||
"transmute from a reference to a reference",
|
||||
|diag| {
|
||||
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
let sugg_paren = arg
|
||||
.as_ty(Ty::new_ptr(cx.tcx, ty_from, from_mutbl))
|
||||
.as_ty(Ty::new_ptr(cx.tcx, ty_to, to_mutbl));
|
||||
let sugg = if to_mutbl == Mutability::Mut {
|
||||
sugg_paren.mut_addr_deref()
|
||||
} else {
|
||||
sugg_paren.addr_deref()
|
||||
};
|
||||
diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
|
||||
}
|
||||
let sugg_paren = arg_sugg()
|
||||
.as_ty(Ty::new_ptr(cx.tcx, ty_from, from_mutbl))
|
||||
.as_ty(Ty::new_ptr(cx.tcx, ty_to, to_mutbl));
|
||||
let sugg = if to_mutbl == Mutability::Mut {
|
||||
sugg_paren.mut_addr_deref()
|
||||
} else {
|
||||
sugg_paren.addr_deref()
|
||||
};
|
||||
diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
|
||||
},
|
||||
);
|
||||
|
||||
triggered = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
triggered
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,4 +128,17 @@ fn bytes_to_str(mb: &mut [u8]) {
|
|||
//~^ transmute_bytes_to_str
|
||||
}
|
||||
|
||||
fn issue16104() {
|
||||
let b = vec![1_u8, 2_u8];
|
||||
macro_rules! take_ref {
|
||||
($x:expr) => {
|
||||
$x.as_slice()
|
||||
};
|
||||
}
|
||||
unsafe {
|
||||
let _: &str = std::mem::transmute(take_ref!(b));
|
||||
//~^ transmute_bytes_to_str
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -106,5 +106,11 @@ error: transmute from a `&[u8]` to a `&str`
|
|||
LL | const _: &str = unsafe { std::mem::transmute(B) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: transmute from a `&[u8]` to a `&str`
|
||||
--> tests/ui/transmute.rs:139:23
|
||||
|
|
||||
LL | let _: &str = std::mem::transmute(take_ref!(b));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(take_ref!(b)).unwrap()`
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -18,3 +18,23 @@ fn main() {
|
|||
//~^ transmute_ptr_to_ptr
|
||||
}
|
||||
}
|
||||
|
||||
fn issue16104(make_ptr: fn() -> *const u32) {
|
||||
macro_rules! call {
|
||||
($x:expr) => {
|
||||
$x()
|
||||
};
|
||||
}
|
||||
macro_rules! take_ref {
|
||||
($x:expr) => {
|
||||
&$x
|
||||
};
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let _: *const f32 = std::mem::transmute(call!(make_ptr));
|
||||
//~^ transmute_ptr_to_ptr
|
||||
let _: &f32 = std::mem::transmute(take_ref!(1u32));
|
||||
//~^ transmute_ptr_to_ptr
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,23 @@ error: transmute from a reference to a reference
|
|||
LL | let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: transmute from a pointer to a pointer
|
||||
--> tests/ui/transmute_ref_to_ref.rs:35:29
|
||||
|
|
||||
LL | let _: *const f32 = std::mem::transmute(call!(make_ptr));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: use `pointer::cast` instead
|
||||
|
|
||||
LL - let _: *const f32 = std::mem::transmute(call!(make_ptr));
|
||||
LL + let _: *const f32 = call!(make_ptr).cast::<f32>();
|
||||
|
|
||||
|
||||
error: transmute from a reference to a reference
|
||||
--> tests/ui/transmute_ref_to_ref.rs:37:23
|
||||
|
|
||||
LL | let _: &f32 = std::mem::transmute(take_ref!(1u32));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(take_ref!(1u32) as *const u32 as *const f32)`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue