From 7c07022c987a9f90218f70defe48b2ddb0824a84 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Wed, 16 Feb 2022 10:45:49 -0500 Subject: [PATCH] Allow transmuting fat pointers to some types in `transmute_undefined_repr` --- .../src/transmute/transmute_undefined_repr.rs | 66 ++++++++++--------- tests/ui/transmute_undefined_repr.rs | 16 ++++- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index 74bdace408c..2630bc4e9ab 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -19,33 +19,39 @@ pub(super) fn check<'tcx>( while from_ty != to_ty { match reduce_refs(cx, e.span, from_ty, to_ty) { - ReducedTys::FromFatPtr { unsized_ty, .. } => { - span_lint_and_then( - cx, - TRANSMUTE_UNDEFINED_REPR, - e.span, - &format!("transmute from `{}` which has an undefined layout", from_ty_orig), - |diag| { - if from_ty_orig.peel_refs() != unsized_ty { - diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty)); - } - }, - ); - return true; + ReducedTys::FromFatPtr { unsized_ty, to_ty } => match reduce_ty(cx, to_ty) { + ReducedTy::IntArray | ReducedTy::TypeErasure => break, + _ => { + span_lint_and_then( + cx, + TRANSMUTE_UNDEFINED_REPR, + e.span, + &format!("transmute from `{}` which has an undefined layout", from_ty_orig), + |diag| { + if from_ty_orig.peel_refs() != unsized_ty { + diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty)); + } + }, + ); + return true; + }, }, - ReducedTys::ToFatPtr { unsized_ty, .. } => { - span_lint_and_then( - cx, - TRANSMUTE_UNDEFINED_REPR, - e.span, - &format!("transmute to `{}` which has an undefined layout", to_ty_orig), - |diag| { - if to_ty_orig.peel_refs() != unsized_ty { - diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty)); - } - }, - ); - return true; + ReducedTys::ToFatPtr { unsized_ty, from_ty } => match reduce_ty(cx, from_ty) { + ReducedTy::IntArray | ReducedTy::TypeErasure => break, + _ => { + span_lint_and_then( + cx, + TRANSMUTE_UNDEFINED_REPR, + e.span, + &format!("transmute to `{}` which has an undefined layout", to_ty_orig), + |diag| { + if to_ty_orig.peel_refs() != unsized_ty { + diag.note(&format!("the contained type `&{}` has an undefined layout", unsized_ty)); + } + }, + ); + return true; + }, }, ReducedTys::ToPtr { from_ty: from_sub_ty, @@ -184,8 +190,8 @@ pub(super) fn check<'tcx>( } enum ReducedTys<'tcx> { - FromFatPtr { unsized_ty: Ty<'tcx> }, - ToFatPtr { unsized_ty: Ty<'tcx> }, + FromFatPtr { unsized_ty: Ty<'tcx>, to_ty: Ty<'tcx> }, + ToFatPtr { unsized_ty: Ty<'tcx>, from_ty: Ty<'tcx> }, ToPtr { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> }, FromPtr { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> }, Other { from_ty: Ty<'tcx>, to_ty: Ty<'tcx> }, @@ -211,12 +217,12 @@ fn reduce_refs<'tcx>( (ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }), _) if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) => { - ReducedTys::FromFatPtr { unsized_ty } + ReducedTys::FromFatPtr { unsized_ty, to_ty } }, (_, ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })) if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) => { - ReducedTys::ToFatPtr { unsized_ty } + ReducedTys::ToFatPtr { unsized_ty, from_ty } }, (ty::Ref(_, from_ty, _) | ty::RawPtr(TypeAndMut { ty: from_ty, .. }), _) => { ReducedTys::FromPtr { from_ty, to_ty } diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs index c1ee0d98a92..84dd1ada8c3 100644 --- a/tests/ui/transmute_undefined_repr.rs +++ b/tests/ui/transmute_undefined_repr.rs @@ -1,8 +1,8 @@ #![warn(clippy::transmute_undefined_repr)] -#![allow(clippy::unit_arg)] +#![allow(clippy::unit_arg, clippy::transmute_ptr_to_ref)] use core::ffi::c_void; -use core::mem::transmute; +use core::mem::{size_of, transmute}; fn value() -> T { unimplemented!() @@ -72,5 +72,17 @@ fn main() { ); let _: *const Erase2 = transmute(value::>>()); // Ok, type erasure let _: Ty<&Ty2> = transmute(value::<*const Erase2>()); // Ok, reverse type erasure + + let _: *const () = transmute(value::<&&[u8]>()); // Ok, type erasure + let _: &&[u8] = transmute(value::<*const ()>()); // Ok, reverse type erasure + + let _: *mut c_void = transmute(value::<&mut &[u8]>()); // Ok, type erasure + let _: &mut &[u8] = transmute(value::<*mut c_void>()); // Ok, reverse type erasure + + let _: [u8; size_of::<&[u8]>()] = transmute(value::<&[u8]>()); // Ok, transmute to byte array + let _: &[u8] = transmute(value::<[u8; size_of::<&[u8]>()]>()); // Ok, transmute from byte array + + let _: [usize; 2] = transmute(value::<&[u8]>()); // Ok, transmute to int array + let _: &[u8] = transmute(value::<[usize; 2]>()); // Ok, transmute from int array } }