Skip to content

Commit 7c07022

Browse files
committed
Allow transmuting fat pointers to some types in transmute_undefined_repr
1 parent 447a245 commit 7c07022

File tree

2 files changed

+50
-32
lines changed

2 files changed

+50
-32
lines changed

clippy_lints/src/transmute/transmute_undefined_repr.rs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,39 @@ pub(super) fn check<'tcx>(
1919

2020
while from_ty != to_ty {
2121
match reduce_refs(cx, e.span, from_ty, to_ty) {
22-
ReducedTys::FromFatPtr { unsized_ty, .. } => {
23-
span_lint_and_then(
24-
cx,
25-
TRANSMUTE_UNDEFINED_REPR,
26-
e.span,
27-
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
28-
|diag| {
29-
if from_ty_orig.peel_refs() != unsized_ty {
30-
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
31-
}
32-
},
33-
);
34-
return true;
22+
ReducedTys::FromFatPtr { unsized_ty, to_ty } => match reduce_ty(cx, to_ty) {
23+
ReducedTy::IntArray | ReducedTy::TypeErasure => break,
24+
_ => {
25+
span_lint_and_then(
26+
cx,
27+
TRANSMUTE_UNDEFINED_REPR,
28+
e.span,
29+
&format!("transmute from `{}` which has an undefined layout", from_ty_orig),
30+
|diag| {
31+
if from_ty_orig.peel_refs() != unsized_ty {
32+
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
33+
}
34+
},
35+
);
36+
return true;
37+
},
3538
},
36-
ReducedTys::ToFatPtr { unsized_ty, .. } => {
37-
span_lint_and_then(
38-
cx,
39-
TRANSMUTE_UNDEFINED_REPR,
40-
e.span,
41-
&format!("transmute to `{}` which has an undefined layout", to_ty_orig),
42-
|diag| {
43-
if to_ty_orig.peel_refs() != unsized_ty {
44-
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
45-
}
46-
},
47-
);
48-
return true;
39+
ReducedTys::ToFatPtr { unsized_ty, from_ty } => match reduce_ty(cx, from_ty) {
40+
ReducedTy::IntArray | ReducedTy::TypeErasure => break,
41+
_ => {
42+
span_lint_and_then(
43+
cx,
44+
TRANSMUTE_UNDEFINED_REPR,
45+
e.span,
46+
&format!("transmute to `{}` which has an undefined layout", to_ty_orig),
47+
|diag| {
48+
if to_ty_orig.peel_refs() != unsized_ty {
49+
diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty));
50+
}
51+
},
52+
);
53+
return true;
54+
},
4955
},
5056
ReducedTys::ToPtr {
5157
from_ty: from_sub_ty,
@@ -184,8 +190,8 @@ pub(super) fn check<'tcx>(
184190
}
185191

186192
enum ReducedTys<'tcx> {
187-
FromFatPtr { unsized_ty: Ty<'tcx> },
188-
ToFatPtr { unsized_ty: Ty<'tcx> },
193+
FromFatPtr { unsized_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
194+
ToFatPtr { unsized_ty: Ty<'tcx>, from_ty: Ty<'tcx> },
189195
ToPtr { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
190196
FromPtr { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
191197
Other { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> },
@@ -211,12 +217,12 @@ fn reduce_refs<'tcx>(
211217
(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }), _)
212218
if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
213219
{
214-
ReducedTys::FromFatPtr { unsized_ty }
220+
ReducedTys::FromFatPtr { unsized_ty, to_ty }
215221
},
216222
(_, ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }))
217223
if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
218224
{
219-
ReducedTys::ToFatPtr { unsized_ty }
225+
ReducedTys::ToFatPtr { unsized_ty, from_ty }
220226
},
221227
(ty::Ref(_, from_ty, _) | ty::RawPtr(TypeAndMut { ty: from_ty, .. }), _) => {
222228
ReducedTys::FromPtr { from_ty, to_ty }

tests/ui/transmute_undefined_repr.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![warn(clippy::transmute_undefined_repr)]
2-
#![allow(clippy::unit_arg)]
2+
#![allow(clippy::unit_arg, clippy::transmute_ptr_to_ref)]
33

44
use core::ffi::c_void;
5-
use core::mem::transmute;
5+
use core::mem::{size_of, transmute};
66

77
fn value<T>() -> T {
88
unimplemented!()
@@ -72,5 +72,17 @@ fn main() {
7272
);
7373
let _: *const Erase2 = transmute(value::<Ty<&Ty2<u32, f32>>>()); // Ok, type erasure
7474
let _: Ty<&Ty2<u32, f32>> = transmute(value::<*const Erase2>()); // Ok, reverse type erasure
75+
76+
let _: *const () = transmute(value::<&&[u8]>()); // Ok, type erasure
77+
let _: &&[u8] = transmute(value::<*const ()>()); // Ok, reverse type erasure
78+
79+
let _: *mut c_void = transmute(value::<&mut &[u8]>()); // Ok, type erasure
80+
let _: &mut &[u8] = transmute(value::<*mut c_void>()); // Ok, reverse type erasure
81+
82+
let _: [u8; size_of::<&[u8]>()] = transmute(value::<&[u8]>()); // Ok, transmute to byte array
83+
let _: &[u8] = transmute(value::<[u8; size_of::<&[u8]>()]>()); // Ok, transmute from byte array
84+
85+
let _: [usize; 2] = transmute(value::<&[u8]>()); // Ok, transmute to int array
86+
let _: &[u8] = transmute(value::<[usize; 2]>()); // Ok, transmute from int array
7587
}
7688
}

0 commit comments

Comments
 (0)