Skip to content

Commit ee73189

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

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed

clippy_lints/src/transmute/wrong_transmute.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,18 @@ 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+
let mut fields = def.variants().iter().filter_map(|v| non_zst_inner_ty(cx, v));
12+
if fields.clone().count() != 1 {
13+
return false;
14+
}
15+
if let Some(field) = fields.next_back() {
16+
from_ty = field.ty(cx.tcx, args);
17+
}
18+
}
1019
match (&from_ty.kind(), &to_ty.kind()) {
11-
(ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_, _)) => {
20+
(ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char, ty::Ref(..) | ty::RawPtr(_, _)) => {
1221
span_lint(
1322
cx,
1423
WRONG_TRANSMUTE,
@@ -20,3 +29,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
2029
_ => false,
2130
}
2231
}
32+
33+
fn non_zst_inner_ty<'a>(cx: &LateContext<'_>, variant: &'a ty::VariantDef) -> Option<&'a ty::FieldDef> {
34+
let tcx = cx.tcx;
35+
let param_env = tcx.param_env(variant.def_id);
36+
variant.fields.iter().find(|field| {
37+
let field_ty = tcx.type_of(field.did).instantiate_identity();
38+
let is_1zst = tcx
39+
.layout_of(param_env.and(field_ty))
40+
.is_ok_and(|layout| layout.is_1zst());
41+
!is_1zst
42+
})
43+
}

tests/ui/transmute_int_to_ptr.rs

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

tests/ui/transmute_int_to_ptr.stderr

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: transmute from a `usize` to a pointer
2+
--> tests/ui/transmute_int_to_ptr.rs:11:22
3+
|
4+
LL | let x = unsafe { std::mem::transmute::<K1, *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: transmute from a `usize` to a pointer
11+
--> tests/ui/transmute_int_to_ptr.rs:22:22
12+
|
13+
LL | let x = unsafe { std::mem::transmute::<K2, *mut i8>(k) };
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
16+
error: aborting due to 2 previous errors
17+

0 commit comments

Comments
 (0)