feat(transmute_ptr_to_ptr): Handle a pointer wrapped in a struct

Now the program checks for transmutting from a struct containing a
single raw pointer to a raw pointer.

changelog: [`transmute_ptr_to_ptr`]: now checks for a pointer wrapped in
a struct
This commit is contained in:
ceptontech 2025-12-01 09:00:29 -08:00
parent 5ac265676a
commit e9ceae44b7
5 changed files with 116 additions and 24 deletions

View file

@ -555,7 +555,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
| transmute_ptr_to_ref::check(cx, e, from_field_ty, to_ty, from_field_expr.clone(), path, self.msrv)
| missing_transmute_annotations::check(cx, path, arg, from_ty, to_ty, e.hir_id)
| 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, self.msrv)
| transmute_ptr_to_ptr::check(cx, e, from_field_ty, to_ty, from_field_expr, self.msrv)
| transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
| transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
| (unsound_collection_transmute::check(cx, e, from_ty, to_ty)

View file

@ -14,11 +14,9 @@ pub(super) fn check<'tcx>(
e: &'tcx Expr<'_>,
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
arg: &'tcx Expr<'_>,
arg: sugg::Sugg<'_>,
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(
@ -34,7 +32,7 @@ pub(super) fn check<'tcx>(
diag.span_suggestion_verbose(
e.span,
"use `pointer::cast` instead",
format!("{}.cast::<{to_pointee_ty}>()", arg_sugg.maybe_paren()),
format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_paren()),
Applicability::MaybeIncorrect,
);
} else if from_pointee_ty == to_pointee_ty
@ -49,14 +47,14 @@ pub(super) fn check<'tcx>(
diag.span_suggestion_verbose(
e.span,
format!("use `pointer::{method}` instead"),
format!("{}.{method}()", arg_sugg.maybe_paren()),
format!("{}.{method}()", arg.maybe_paren()),
Applicability::MaybeIncorrect,
);
} else {
diag.span_suggestion_verbose(
e.span,
"use an `as` cast instead",
arg_sugg.as_ty(to_ty),
arg.as_ty(to_ty),
Applicability::MaybeIncorrect,
);
}

View file

@ -24,6 +24,13 @@ struct GenericParam<T> {
t: T,
}
#[derive(Clone, Copy)]
struct PtrNamed {
ptr: *const u32,
}
#[derive(Clone, Copy)]
struct Ptr(*const u32);
fn transmute_ptr_to_ptr() {
let ptr = &1u32 as *const u32;
let mut_ptr = &mut 1u32 as *mut u32;
@ -68,6 +75,18 @@ fn transmute_ptr_to_ptr() {
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
}
fn issue1966() {
let ptr = &1u32 as *const u32;
unsafe {
let _: *const f32 = Ptr(ptr).0.cast::<f32>();
//~^ transmute_ptr_to_ptr
let _: *const f32 = PtrNamed { ptr }.ptr.cast::<f32>();
//~^ transmute_ptr_to_ptr
let _: *mut u32 = Ptr(ptr).0.cast_mut();
//~^ transmute_ptr_to_ptr
}
}
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
unsafe { v as *const &() }
//~^ transmute_ptr_to_ptr
@ -81,11 +100,15 @@ const _: &() = {
unsafe { transmute::<&'static Zst, &'static ()>(zst) }
};
#[derive(Clone, Copy)]
struct Ptr8(*const u8);
#[clippy::msrv = "1.37"]
fn msrv_1_37(ptr: *const u8) {
unsafe {
let _: *const i8 = ptr as *const i8;
//~^ transmute_ptr_to_ptr
let _: *const i8 = Ptr8(ptr).0 as *const i8;
//~^ transmute_ptr_to_ptr
}
}

View file

@ -24,6 +24,13 @@ struct GenericParam<T> {
t: T,
}
#[derive(Clone, Copy)]
struct PtrNamed {
ptr: *const u32,
}
#[derive(Clone, Copy)]
struct Ptr(*const u32);
fn transmute_ptr_to_ptr() {
let ptr = &1u32 as *const u32;
let mut_ptr = &mut 1u32 as *mut u32;
@ -68,6 +75,18 @@ fn transmute_ptr_to_ptr() {
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
}
fn issue1966() {
let ptr = &1u32 as *const u32;
unsafe {
let _: *const f32 = transmute(Ptr(ptr));
//~^ transmute_ptr_to_ptr
let _: *const f32 = transmute(PtrNamed { ptr });
//~^ transmute_ptr_to_ptr
let _: *mut u32 = transmute(Ptr(ptr));
//~^ transmute_ptr_to_ptr
}
}
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
unsafe { transmute(v) }
//~^ transmute_ptr_to_ptr
@ -81,11 +100,15 @@ const _: &() = {
unsafe { transmute::<&'static Zst, &'static ()>(zst) }
};
#[derive(Clone, Copy)]
struct Ptr8(*const u8);
#[clippy::msrv = "1.37"]
fn msrv_1_37(ptr: *const u8) {
unsafe {
let _: *const i8 = transmute(ptr);
//~^ transmute_ptr_to_ptr
let _: *const i8 = transmute(Ptr8(ptr));
//~^ transmute_ptr_to_ptr
}
}

View file

@ -1,5 +1,5 @@
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:32:29
--> tests/ui/transmute_ptr_to_ptr.rs:39:29
|
LL | let _: *const f32 = transmute(ptr);
| ^^^^^^^^^^^^^^
@ -13,7 +13,7 @@ LL + let _: *const f32 = ptr.cast::<f32>();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:35:27
--> tests/ui/transmute_ptr_to_ptr.rs:42:27
|
LL | let _: *mut f32 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
@ -25,37 +25,37 @@ LL + let _: *mut f32 = mut_ptr.cast::<f32>();
|
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:39:23
--> tests/ui/transmute_ptr_to_ptr.rs:46:23
|
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:42:23
--> tests/ui/transmute_ptr_to_ptr.rs:49:23
|
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:47:27
--> tests/ui/transmute_ptr_to_ptr.rs:54:27
|
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:50:37
--> tests/ui/transmute_ptr_to_ptr.rs:57:37
|
LL | let _: &GenericParam<f32> = transmute(&GenericParam { t: 1u32 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:54:27
--> tests/ui/transmute_ptr_to_ptr.rs:61: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:57:29
--> tests/ui/transmute_ptr_to_ptr.rs:64:29
|
LL | let _: *const u32 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
@ -67,7 +67,7 @@ LL + let _: *const u32 = mut_ptr.cast_const();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:60:27
--> tests/ui/transmute_ptr_to_ptr.rs:67:27
|
LL | let _: *mut u32 = transmute(ptr);
| ^^^^^^^^^^^^^^
@ -79,7 +79,43 @@ LL + let _: *mut u32 = ptr.cast_mut();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:72:14
--> tests/ui/transmute_ptr_to_ptr.rs:81:29
|
LL | let _: *const f32 = transmute(Ptr(ptr));
| ^^^^^^^^^^^^^^^^^^^
|
help: use `pointer::cast` instead
|
LL - let _: *const f32 = transmute(Ptr(ptr));
LL + let _: *const f32 = Ptr(ptr).0.cast::<f32>();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:83:29
|
LL | let _: *const f32 = transmute(PtrNamed { ptr });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: use `pointer::cast` instead
|
LL - let _: *const f32 = transmute(PtrNamed { ptr });
LL + let _: *const f32 = PtrNamed { ptr }.ptr.cast::<f32>();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:85:27
|
LL | let _: *mut u32 = transmute(Ptr(ptr));
| ^^^^^^^^^^^^^^^^^^^
|
help: use `pointer::cast_mut` instead
|
LL - let _: *mut u32 = transmute(Ptr(ptr));
LL + let _: *mut u32 = Ptr(ptr).0.cast_mut();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:91:14
|
LL | unsafe { transmute(v) }
| ^^^^^^^^^^^^
@ -91,7 +127,7 @@ LL + unsafe { v as *const &() }
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:87:28
--> tests/ui/transmute_ptr_to_ptr.rs:108:28
|
LL | let _: *const i8 = transmute(ptr);
| ^^^^^^^^^^^^^^
@ -103,7 +139,19 @@ LL + let _: *const i8 = ptr as *const i8;
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:95:28
--> tests/ui/transmute_ptr_to_ptr.rs:110:28
|
LL | let _: *const i8 = transmute(Ptr8(ptr));
| ^^^^^^^^^^^^^^^^^^^^
|
help: use an `as` cast instead
|
LL - let _: *const i8 = transmute(Ptr8(ptr));
LL + let _: *const i8 = Ptr8(ptr).0 as *const i8;
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:118:28
|
LL | let _: *const i8 = transmute(ptr);
| ^^^^^^^^^^^^^^
@ -115,7 +163,7 @@ LL + let _: *const i8 = ptr.cast::<i8>();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:103:26
--> tests/ui/transmute_ptr_to_ptr.rs:126:26
|
LL | let _: *mut u8 = transmute(ptr);
| ^^^^^^^^^^^^^^
@ -127,7 +175,7 @@ LL + let _: *mut u8 = ptr as *mut u8;
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:105:28
--> tests/ui/transmute_ptr_to_ptr.rs:128:28
|
LL | let _: *const u8 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
@ -139,7 +187,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:113:26
--> tests/ui/transmute_ptr_to_ptr.rs:136:26
|
LL | let _: *mut u8 = transmute(ptr);
| ^^^^^^^^^^^^^^
@ -151,7 +199,7 @@ LL + let _: *mut u8 = ptr.cast_mut();
|
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:115:28
--> tests/ui/transmute_ptr_to_ptr.rs:138:28
|
LL | let _: *const u8 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
@ -162,5 +210,5 @@ LL - let _: *const u8 = transmute(mut_ptr);
LL + let _: *const u8 = mut_ptr.cast_const();
|
error: aborting due to 16 previous errors
error: aborting due to 20 previous errors