Skip to content

Commit f00f10a

Browse files
committed
feat: lint transmute int to ptr
1 parent c6f45df commit f00f10a

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

clippy_lints/src/transmute/wrong_transmute.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,21 @@ use rustc_middle::ty::{self, Ty};
66

77
/// Checks for `wrong_transmute` lint.
88
/// Returns `true` if it's triggered, otherwise returns `false`.
9-
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool {
9+
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, mut from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool {
10+
if let ty::Adt(def, args) = from_ty.kind() {
11+
if def.repr().transparent() {
12+
if let Some(field) = def
13+
.variants()
14+
.iter()
15+
.filter_map(|v| transparent_non_zst_inner_ty(cx, v))
16+
.next_back()
17+
{
18+
from_ty = field.ty(cx.tcx, args);
19+
}
20+
}
21+
}
1022
match (&from_ty.kind(), &to_ty.kind()) {
11-
(ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_, _)) => {
23+
(ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_, _)) => {
1224
span_lint(
1325
cx,
1426
WRONG_TRANSMUTE,
@@ -20,3 +32,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
2032
_ => false,
2133
}
2234
}
35+
36+
fn transparent_non_zst_inner_ty<'a>(cx: &LateContext<'_>, variant: &'a ty::VariantDef) -> Option<&'a ty::FieldDef> {
37+
let tcx = cx.tcx;
38+
let param_env = tcx.param_env(variant.def_id);
39+
variant.fields.iter().find(|field| {
40+
let field_ty = tcx.type_of(field.did).instantiate_identity();
41+
let is_1zst = tcx
42+
.layout_of(param_env.and(field_ty))
43+
.is_ok_and(|layout| layout.is_1zst());
44+
!is_1zst
45+
})
46+
}

tests/ui/transmute_32bit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ fn main() {
1010
let _: *const usize = std::mem::transmute('x');
1111

1212
let _: *mut usize = std::mem::transmute('x');
13+
14+
let _: *mut usize = std::mem::transmute(6u32);
1315
}
1416
}

tests/ui/transmute_int_to_ptr.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![warn(clippy::wrong_transmute)]
2+
3+
#[repr(transparent)]
4+
pub struct K {
5+
b: usize,
6+
c: (),
7+
}
8+
9+
pub fn foo(k: K) {
10+
let x = unsafe { std::mem::transmute::<K, *mut i8>(k) };
11+
std::hint::black_box(unsafe { *x });
12+
}
13+
14+
fn main() {
15+
let x = 0_i8;
16+
foo(K {
17+
b: &x as *const i8 as usize,
18+
c: (),
19+
});
20+
}

tests/ui/transmute_int_to_ptr.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: transmute from a `usize` to a pointer
2+
--> tests/ui/transmute_int_to_ptr.rs:10:22
3+
|
4+
LL | let x = unsafe { std::mem::transmute::<K, *mut i8>(k) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::wrong-transmute` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::wrong_transmute)]`
9+
10+
error: aborting due to 1 previous error
11+

0 commit comments

Comments
 (0)