From afe811ad30198c966c6b69516c2a83f531c5c982 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 22 Jul 2024 17:20:23 +0000 Subject: [PATCH 1/2] Suggest `.cast`/`.cast_const`/`.cast_mut` in `transmute_ptr_as_ptr` --- clippy_lints/src/transmute/mod.rs | 2 +- .../src/transmute/transmute_ptr_to_ptr.rs | 40 ++++- tests/ui/transmute_ptr_to_ptr.fixed | 74 ++++++--- tests/ui/transmute_ptr_to_ptr.rs | 82 ++++++---- tests/ui/transmute_ptr_to_ptr.stderr | 141 +++++++++++++++--- .../transmutes_expressible_as_ptr_casts.fixed | 2 +- ...transmutes_expressible_as_ptr_casts.stderr | 13 +- 7 files changed, 274 insertions(+), 80 deletions(-) diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index e556d5867bba..9c6813a54b94 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -617,7 +617,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id) | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) + | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 1476ea8e7a4e..36a8e9163a04 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -1,4 +1,5 @@ use super::TRANSMUTE_PTR_TO_PTR; +use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg; use rustc_errors::Applicability; @@ -14,9 +15,10 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, + msrv: &Msrv, ) -> bool { - match (&from_ty.kind(), &to_ty.kind()) { - (ty::RawPtr(_, _), ty::RawPtr(to_ty, to_mutbl)) => { + 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( cx, TRANSMUTE_PTR_TO_PTR, @@ -24,8 +26,38 @@ pub(super) fn check<'tcx>( "transmute from a pointer to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let sugg = arg.as_ty(Ty::new_ptr(cx.tcx, *to_ty, *to_mutbl)); - diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); + if from_mutbl == to_mutbl + && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && msrv.meets(msrvs::POINTER_CAST) + { + diag.span_suggestion_verbose( + e.span, + "use `pointer::cast` instead", + format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_par()), + 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, + } + && msrv.meets(msrvs::POINTER_CAST_CONSTNESS) + { + diag.span_suggestion_verbose( + e.span, + format!("use `pointer::{method}` instead"), + format!("{}.{method}()", arg.maybe_par()), + Applicability::MaybeIncorrect, + ); + } else { + diag.span_suggestion_verbose( + e.span, + "use an `as` cast instead", + arg.as_ty(to_ty), + Applicability::MaybeIncorrect, + ); + } } }, ); diff --git a/tests/ui/transmute_ptr_to_ptr.fixed b/tests/ui/transmute_ptr_to_ptr.fixed index b696a574ae39..7a84f2b53f6b 100644 --- a/tests/ui/transmute_ptr_to_ptr.fixed +++ b/tests/ui/transmute_ptr_to_ptr.fixed @@ -1,17 +1,19 @@ #![warn(clippy::transmute_ptr_to_ptr)] #![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] +use std::mem::transmute; + // Make sure we can modify lifetimes, which is one of the recommended uses // of transmute // Make sure we can do static lifetime transmutes unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T { - std::mem::transmute::<&'a T, &'static T>(t) + transmute::<&'a T, &'static T>(t) } // Make sure we can do non-static lifetime transmutes unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T { - std::mem::transmute::<&'a T, &'b T>(t) + transmute::<&'a T, &'b T>(t) } struct LifetimeParam<'a> { @@ -27,39 +29,35 @@ fn transmute_ptr_to_ptr() { let mut_ptr = &mut 1u32 as *mut u32; unsafe { // pointer-to-pointer transmutes; bad - let _: *const f32 = ptr as *const f32; - //~^ ERROR: transmute from a pointer to a pointer - //~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` - let _: *mut f32 = mut_ptr as *mut f32; - //~^ ERROR: transmute from a pointer to a pointer + let _: *const f32 = ptr.cast::(); + //~^ transmute_ptr_to_ptr + let _: *mut f32 = mut_ptr.cast::(); + //~^ transmute_ptr_to_ptr // ref-ref transmutes; bad let _: &f32 = &*(&1u32 as *const u32 as *const f32); - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr let _: &f32 = &*(&1f64 as *const f64 as *const f32); - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not // the same type let _: &mut f32 = &mut *(&mut 1u32 as *mut u32 as *mut f32); - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr let _: &GenericParam = &*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam); - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr let u64_ref: &u64 = &0u64; - let u8_ref: &u8 = unsafe { &*(u64_ref as *const u64 as *const u8) }; - //~^ ERROR: transmute from a reference to a reference + let u8_ref: &u8 = &*(u64_ref as *const u64 as *const u8); + //~^ transmute_ptr_to_ptr + let _: *const u32 = mut_ptr.cast_const(); + //~^ transmute_ptr_to_ptr + let _: *mut u32 = ptr.cast_mut(); + //~^ transmute_ptr_to_ptr } - // these are recommendations for solving the above; if these lint we need to update - // those suggestions - let _ = ptr as *const f32; - let _ = mut_ptr as *mut f32; - let _ = unsafe { &*(&1u32 as *const u32 as *const f32) }; - let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) }; - // transmute internal lifetimes, should not lint let s = "hello world".to_owned(); let lp = LifetimeParam { s: &s }; - let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) }; - let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) }; + let _: &LifetimeParam<'static> = unsafe { transmute(&lp) }; + let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) }; } // dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959) @@ -67,7 +65,37 @@ const _: &() = { struct Zst; let zst = &Zst; - unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) } + unsafe { transmute::<&'static Zst, &'static ()>(zst) } }; +#[clippy::msrv = "1.37"] +fn msrv_1_37(ptr: *const u8) { + unsafe { + let _: *const i8 = ptr as *const i8; + } +} + +#[clippy::msrv = "1.38"] +fn msrv_1_38(ptr: *const u8) { + unsafe { + let _: *const i8 = ptr.cast::(); + } +} + +#[clippy::msrv = "1.64"] +fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) { + unsafe { + let _: *mut u8 = ptr as *mut u8; + let _: *const u8 = mut_ptr as *const u8; + } +} + +#[clippy::msrv = "1.65"] +fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) { + unsafe { + let _: *mut u8 = ptr.cast_mut(); + let _: *const u8 = mut_ptr.cast_const(); + } +} + fn main() {} diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index 85cc1d7802c2..1dc8e2af5bbf 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -1,17 +1,19 @@ #![warn(clippy::transmute_ptr_to_ptr)] #![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] +use std::mem::transmute; + // Make sure we can modify lifetimes, which is one of the recommended uses // of transmute // Make sure we can do static lifetime transmutes unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T { - std::mem::transmute::<&'a T, &'static T>(t) + transmute::<&'a T, &'static T>(t) } // Make sure we can do non-static lifetime transmutes unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T { - std::mem::transmute::<&'a T, &'b T>(t) + transmute::<&'a T, &'b T>(t) } struct LifetimeParam<'a> { @@ -27,39 +29,35 @@ fn transmute_ptr_to_ptr() { let mut_ptr = &mut 1u32 as *mut u32; unsafe { // pointer-to-pointer transmutes; bad - let _: *const f32 = std::mem::transmute(ptr); - //~^ ERROR: transmute from a pointer to a pointer - //~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` - let _: *mut f32 = std::mem::transmute(mut_ptr); - //~^ ERROR: transmute from a pointer to a pointer + let _: *const f32 = transmute(ptr); + //~^ transmute_ptr_to_ptr + let _: *mut f32 = transmute(mut_ptr); + //~^ transmute_ptr_to_ptr // ref-ref transmutes; bad - let _: &f32 = std::mem::transmute(&1u32); - //~^ ERROR: transmute from a reference to a reference - let _: &f32 = std::mem::transmute(&1f64); - //~^ ERROR: transmute from a reference to a reference + let _: &f32 = transmute(&1u32); + //~^ transmute_ptr_to_ptr + let _: &f32 = transmute(&1f64); + //~^ transmute_ptr_to_ptr //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not // the same type - let _: &mut f32 = std::mem::transmute(&mut 1u32); - //~^ ERROR: transmute from a reference to a reference - let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); - //~^ ERROR: transmute from a reference to a reference + let _: &mut f32 = transmute(&mut 1u32); + //~^ transmute_ptr_to_ptr + let _: &GenericParam = transmute(&GenericParam { t: 1u32 }); + //~^ transmute_ptr_to_ptr let u64_ref: &u64 = &0u64; - let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) }; - //~^ ERROR: transmute from a reference to a reference + let u8_ref: &u8 = transmute(u64_ref); + //~^ transmute_ptr_to_ptr + let _: *const u32 = transmute(mut_ptr); + //~^ transmute_ptr_to_ptr + let _: *mut u32 = transmute(ptr); + //~^ transmute_ptr_to_ptr } - // these are recommendations for solving the above; if these lint we need to update - // those suggestions - let _ = ptr as *const f32; - let _ = mut_ptr as *mut f32; - let _ = unsafe { &*(&1u32 as *const u32 as *const f32) }; - let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) }; - // transmute internal lifetimes, should not lint let s = "hello world".to_owned(); let lp = LifetimeParam { s: &s }; - let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) }; - let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) }; + let _: &LifetimeParam<'static> = unsafe { transmute(&lp) }; + let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) }; } // dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959) @@ -67,7 +65,37 @@ const _: &() = { struct Zst; let zst = &Zst; - unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) } + unsafe { transmute::<&'static Zst, &'static ()>(zst) } }; +#[clippy::msrv = "1.37"] +fn msrv_1_37(ptr: *const u8) { + unsafe { + let _: *const i8 = transmute(ptr); + } +} + +#[clippy::msrv = "1.38"] +fn msrv_1_38(ptr: *const u8) { + unsafe { + let _: *const i8 = transmute(ptr); + } +} + +#[clippy::msrv = "1.64"] +fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) { + unsafe { + let _: *mut u8 = transmute(ptr); + let _: *const u8 = transmute(mut_ptr); + } +} + +#[clippy::msrv = "1.65"] +fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) { + unsafe { + let _: *mut u8 = transmute(ptr); + let _: *const u8 = transmute(mut_ptr); + } +} + fn main() {} diff --git a/tests/ui/transmute_ptr_to_ptr.stderr b/tests/ui/transmute_ptr_to_ptr.stderr index cd1f1f398dc2..429341289a3f 100644 --- a/tests/ui/transmute_ptr_to_ptr.stderr +++ b/tests/ui/transmute_ptr_to_ptr.stderr @@ -1,47 +1,144 @@ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:30:29 + --> tests/ui/transmute_ptr_to_ptr.rs:32:29 | -LL | let _: *const f32 = std::mem::transmute(ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32` +LL | let _: *const f32 = transmute(ptr); + | ^^^^^^^^^^^^^^ | = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ptr)]` +help: use `pointer::cast` instead + | +LL | let _: *const f32 = ptr.cast::(); + | ~~~~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:33:27 + --> tests/ui/transmute_ptr_to_ptr.rs:34:27 + | +LL | let _: *mut f32 = transmute(mut_ptr); + | ^^^^^^^^^^^^^^^^^^ + | +help: use `pointer::cast` instead | -LL | let _: *mut f32 = std::mem::transmute(mut_ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32` +LL | let _: *mut f32 = mut_ptr.cast::(); + | ~~~~~~~~~~~~~~~~~~~~~ error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:36:23 + --> tests/ui/transmute_ptr_to_ptr.rs:37:23 | -LL | let _: &f32 = std::mem::transmute(&1u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` +LL | let _: &f32 = transmute(&1u32); + | ^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:38:23 + --> tests/ui/transmute_ptr_to_ptr.rs:39:23 | -LL | let _: &f32 = std::mem::transmute(&1f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)` +LL | let _: &f32 = transmute(&1f64); + | ^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:42:27 + --> tests/ui/transmute_ptr_to_ptr.rs:43:27 | -LL | let _: &mut f32 = std::mem::transmute(&mut 1u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` +LL | let _: &mut f32 = transmute(&mut 1u32); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:44:37 + --> tests/ui/transmute_ptr_to_ptr.rs:45:37 | -LL | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` +LL | let _: &GenericParam = transmute(&GenericParam { t: 1u32 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:47:36 + --> tests/ui/transmute_ptr_to_ptr.rs:48:27 + | +LL | let u8_ref: &u8 = transmute(u64_ref); + | ^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)` + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:50:29 + | +LL | let _: *const u32 = transmute(mut_ptr); + | ^^^^^^^^^^^^^^^^^^ + | +help: use `pointer::cast_const` instead + | +LL | let _: *const u32 = mut_ptr.cast_const(); + | ~~~~~~~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:52:27 + | +LL | let _: *mut u32 = transmute(ptr); + | ^^^^^^^^^^^^^^ + | +help: use `pointer::cast_mut` instead + | +LL | let _: *mut u32 = ptr.cast_mut(); + | ~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:74:28 + | +LL | let _: *const i8 = transmute(ptr); + | ^^^^^^^^^^^^^^ + | +help: use an `as` cast instead + | +LL | let _: *const i8 = ptr as *const i8; + | ~~~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:81:28 + | +LL | let _: *const i8 = transmute(ptr); + | ^^^^^^^^^^^^^^ + | +help: use `pointer::cast` instead + | +LL | let _: *const i8 = ptr.cast::(); + | ~~~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:88:26 + | +LL | let _: *mut u8 = transmute(ptr); + | ^^^^^^^^^^^^^^ + | +help: use an `as` cast instead + | +LL | let _: *mut u8 = ptr as *mut u8; + | ~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:89:28 + | +LL | let _: *const u8 = transmute(mut_ptr); + | ^^^^^^^^^^^^^^^^^^ + | +help: use an `as` cast instead + | +LL | let _: *const u8 = mut_ptr as *const u8; + | ~~~~~~~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:96:26 + | +LL | let _: *mut u8 = transmute(ptr); + | ^^^^^^^^^^^^^^ + | +help: use `pointer::cast_mut` instead + | +LL | let _: *mut u8 = ptr.cast_mut(); + | ~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:97:28 + | +LL | let _: *const u8 = transmute(mut_ptr); + | ^^^^^^^^^^^^^^^^^^ + | +help: use `pointer::cast_const` instead | -LL | let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)` +LL | let _: *const u8 = mut_ptr.cast_const(); + | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 7 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 51682da4a988..e95054a7ccb0 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -18,7 +18,7 @@ fn main() { let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... - let _ptr_i8_transmute = unsafe { ptr_i32 as *const i8 }; + let _ptr_i8_transmute = unsafe { ptr_i32.cast::() }; let _ptr_i8 = ptr_i32 as *const i8; let slice_ptr = &[0, 1, 2, 3] as *const [i32]; diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 2ca44485826d..2d74967ede56 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -11,16 +11,25 @@ error: transmute from a pointer to a pointer --> tests/ui/transmutes_expressible_as_ptr_casts.rs:21:38 | LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ptr)]` +help: use `pointer::cast` instead + | +LL | let _ptr_i8_transmute = unsafe { ptr_i32.cast::() }; + | ~~~~~~~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer --> tests/ui/transmutes_expressible_as_ptr_casts.rs:27:46 | LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u32]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use an `as` cast instead + | +LL | let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] }; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead --> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50 From 7010d3c67ed0f3394f1a8ad2265528c18867a892 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 23 Jul 2024 11:11:22 +0000 Subject: [PATCH 2/2] Don't suggest `.cast_mut`/`.cast_const` for types with erased lifetimes --- clippy_lints/src/casts/ptr_cast_constness.rs | 3 ++- .../src/transmute/transmute_ptr_to_ptr.rs | 3 ++- tests/ui/ptr_cast_constness.fixed | 4 +++ tests/ui/ptr_cast_constness.rs | 4 +++ tests/ui/ptr_cast_constness.stderr | 4 +-- tests/ui/transmute_ptr_to_ptr.fixed | 5 ++++ tests/ui/transmute_ptr_to_ptr.rs | 5 ++++ tests/ui/transmute_ptr_to_ptr.stderr | 25 +++++++++++++------ 8 files changed, 42 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 921693567fcd..7513e18d408b 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -4,7 +4,7 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use super::PTR_CAST_CONSTNESS; @@ -24,6 +24,7 @@ pub(super) fn check<'tcx>( (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not) ) && from_ty == to_ty + && !from_ty.has_erased_regions() { let sugg = Sugg::hir(cx, cast_expr, "_"); let constness = match *to_mutbl { diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 36a8e9163a04..0772b284968a 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -5,7 +5,7 @@ use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; /// Checks for `transmute_ptr_to_ptr` lint. /// Returns `true` if it's triggered, otherwise returns `false`. @@ -42,6 +42,7 @@ pub(super) fn check<'tcx>( (ty::Mutability::Mut, ty::Mutability::Not) => Some("cast_const"), _ => None, } + && !from_pointee_ty.has_erased_regions() && msrv.meets(msrvs::POINTER_CAST_CONSTNESS) { diag.span_suggestion_verbose( diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 33c0725faad0..21ac42196e1b 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -46,6 +46,10 @@ fn main() { let _ = external!($ptr as *const u32); } +fn lifetime_to_static(v: *mut &()) -> *const &'static () { + v as _ +} + #[clippy::msrv = "1.64"] fn _msrv_1_64() { let ptr: *const u32 = &42_u32; diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 24d959856dbd..5ce590b2b7e4 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -46,6 +46,10 @@ fn main() { let _ = external!($ptr as *const u32); } +fn lifetime_to_static(v: *mut &()) -> *const &'static () { + v as _ +} + #[clippy::msrv = "1.64"] fn _msrv_1_64() { let ptr: *const u32 = &42_u32; diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 322c3585e62f..2c52ebd3464d 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -32,13 +32,13 @@ LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:64:13 + --> tests/ui/ptr_cast_constness.rs:68:13 | LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:65:13 + --> tests/ui/ptr_cast_constness.rs:69:13 | LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` diff --git a/tests/ui/transmute_ptr_to_ptr.fixed b/tests/ui/transmute_ptr_to_ptr.fixed index 7a84f2b53f6b..39e67b250526 100644 --- a/tests/ui/transmute_ptr_to_ptr.fixed +++ b/tests/ui/transmute_ptr_to_ptr.fixed @@ -60,6 +60,11 @@ fn transmute_ptr_to_ptr() { let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) }; } +fn lifetime_to_static(v: *mut &()) -> *const &'static () { + unsafe { v as *const &() } + //~^ transmute_ptr_to_ptr +} + // dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959) const _: &() = { struct Zst; diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index 1dc8e2af5bbf..580b28551734 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -60,6 +60,11 @@ fn transmute_ptr_to_ptr() { let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) }; } +fn lifetime_to_static(v: *mut &()) -> *const &'static () { + unsafe { transmute(v) } + //~^ transmute_ptr_to_ptr +} + // dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959) const _: &() = { struct Zst; diff --git a/tests/ui/transmute_ptr_to_ptr.stderr b/tests/ui/transmute_ptr_to_ptr.stderr index 429341289a3f..8801eb943ce8 100644 --- a/tests/ui/transmute_ptr_to_ptr.stderr +++ b/tests/ui/transmute_ptr_to_ptr.stderr @@ -75,7 +75,18 @@ LL | let _: *mut u32 = ptr.cast_mut(); | ~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:74:28 + --> tests/ui/transmute_ptr_to_ptr.rs:64:14 + | +LL | unsafe { transmute(v) } + | ^^^^^^^^^^^^ + | +help: use an `as` cast instead + | +LL | unsafe { v as *const &() } + | ~~~~~~~~~~~~~~~ + +error: transmute from a pointer to a pointer + --> tests/ui/transmute_ptr_to_ptr.rs:79:28 | LL | let _: *const i8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -86,7 +97,7 @@ LL | let _: *const i8 = ptr as *const i8; | ~~~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:81:28 + --> tests/ui/transmute_ptr_to_ptr.rs:86:28 | LL | let _: *const i8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -97,7 +108,7 @@ LL | let _: *const i8 = ptr.cast::(); | ~~~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:88:26 + --> tests/ui/transmute_ptr_to_ptr.rs:93:26 | LL | let _: *mut u8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -108,7 +119,7 @@ LL | let _: *mut u8 = ptr as *mut u8; | ~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:89:28 + --> tests/ui/transmute_ptr_to_ptr.rs:94:28 | LL | let _: *const u8 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -119,7 +130,7 @@ LL | let _: *const u8 = mut_ptr as *const u8; | ~~~~~~~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:96:26 + --> tests/ui/transmute_ptr_to_ptr.rs:101:26 | LL | let _: *mut u8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -130,7 +141,7 @@ LL | let _: *mut u8 = ptr.cast_mut(); | ~~~~~~~~~~~~~~ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:97:28 + --> tests/ui/transmute_ptr_to_ptr.rs:102:28 | LL | let _: *const u8 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -140,5 +151,5 @@ help: use `pointer::cast_const` instead LL | let _: *const u8 = mut_ptr.cast_const(); | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors