diff options
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs')
-rw-r--r-- | src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs | 164 |
1 files changed, 66 insertions, 98 deletions
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 3d4bbbf64..34642f4b1 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -27,32 +27,24 @@ pub(super) fn check<'tcx>( // `Repr(C)` <-> unordered type. // If the first field of the `Repr(C)` type matches then the transmute is ok - ( - ReducedTy::OrderedFields(_, Some(from_sub_ty)), - ReducedTy::UnorderedFields(to_sub_ty), - ) - | ( - ReducedTy::UnorderedFields(from_sub_ty), - ReducedTy::OrderedFields(_, Some(to_sub_ty)), - ) => { + (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::UnorderedFields(to_sub_ty)) + | (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => { from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - } - (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) - if reduced_tys.to_fat_ptr => - { + }, + (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => { from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - } + }, (ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) if reduced_tys.from_fat_ptr => { from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - } + }, // ptr <-> ptr (ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty)) @@ -62,19 +54,19 @@ pub(super) fn check<'tcx>( from_ty = from_sub_ty; to_ty = to_sub_ty; continue; - } + }, // fat ptr <-> (*size, *size) (ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty)) if reduced_tys.from_fat_ptr && is_size_pair(to_ty) => { return false; - } + }, (ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_)) if reduced_tys.to_fat_ptr && is_size_pair(from_ty) => { return false; - } + }, // fat ptr -> some struct | some struct -> fat ptr (ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => { @@ -85,14 +77,12 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty.peel_refs() { - diag.note(&format!( - "the contained type `{from_ty}` has an undefined layout" - )); + diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); } }, ); return true; - } + }, (_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => { span_lint_and_then( cx, @@ -101,18 +91,14 @@ pub(super) fn check<'tcx>( &format!("transmute to `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty.peel_refs() { - diag.note(&format!( - "the contained type `{to_ty}` has an undefined layout" - )); + diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); } }, ); return true; - } + }, - (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) - if from_ty != to_ty => - { + (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => { let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs)) = (from_ty.kind(), to_ty.kind()) && from_def == to_def @@ -139,25 +125,19 @@ pub(super) fn check<'tcx>( )); } else { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!( - "the contained type `{from_ty}` has an undefined layout" - )); + diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); } if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!( - "the contained type `{to_ty}` has an undefined layout" - )); + diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); } } }, ); return true; - } + }, ( ReducedTy::UnorderedFields(from_ty), - ReducedTy::Other(_) - | ReducedTy::OrderedFields(..) - | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true }, ) => { span_lint_and_then( cx, @@ -166,18 +146,14 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!( - "the contained type `{from_ty}` has an undefined layout" - )); + diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); } }, ); return true; - } + }, ( - ReducedTy::Other(_) - | ReducedTy::OrderedFields(..) - | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true }, ReducedTy::UnorderedFields(to_ty), ) => { span_lint_and_then( @@ -187,25 +163,19 @@ pub(super) fn check<'tcx>( &format!("transmute into `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!( - "the contained type `{to_ty}` has an undefined layout" - )); + diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); } }, ); return true; - } + }, ( - ReducedTy::OrderedFields(..) - | ReducedTy::Other(_) - | ReducedTy::TypeErasure { raw_ptr_only: true }, - ReducedTy::OrderedFields(..) - | ReducedTy::Other(_) - | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true }, + ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true }, ) | (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => { break; - } + }, } } @@ -223,38 +193,42 @@ struct ReducedTys<'tcx> { } /// Remove references so long as both types are references. -fn reduce_refs<'tcx>( - cx: &LateContext<'tcx>, - mut from_ty: Ty<'tcx>, - mut to_ty: Ty<'tcx>, -) -> ReducedTys<'tcx> { +fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: Ty<'tcx>) -> ReducedTys<'tcx> { let mut from_raw_ptr = false; let mut to_raw_ptr = false; - let (from_fat_ptr, to_fat_ptr) = - loop { - break match (from_ty.kind(), to_ty.kind()) { - ( - &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })), - &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })), - ) => { - from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_)); - from_ty = from_sub_ty; - to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_)); - to_ty = to_sub_ty; - continue; - } - ( - &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), - _, - ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (true, false), - ( - _, - &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), - ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (false, true), - _ => (false, false), - }; + let (from_fat_ptr, to_fat_ptr) = loop { + break match (from_ty.kind(), to_ty.kind()) { + ( + &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })), + &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })), + ) => { + from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_)); + from_ty = from_sub_ty; + to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_)); + to_ty = to_sub_ty; + continue; + }, + (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _) + if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + { + (true, false) + }, + (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }))) + if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + { + (false, true) + }, + _ => (false, false), }; - ReducedTys { from_ty, to_ty, from_raw_ptr, to_raw_ptr, from_fat_ptr, to_fat_ptr } + }; + ReducedTys { + from_ty, + to_ty, + from_raw_ptr, + to_raw_ptr, + from_fat_ptr, + to_fat_ptr, + } } enum ReducedTy<'tcx> { @@ -277,11 +251,11 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> return match *ty.kind() { ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ReducedTy::TypeErasure { raw_ptr_only: false } - } + }, ty::Array(sub_ty, _) | ty::Slice(sub_ty) => { ty = sub_ty; continue; - } + }, ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Tuple(args) => { let mut iter = args.iter(); @@ -293,7 +267,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> continue; } ReducedTy::UnorderedFields(ty) - } + }, ty::Adt(def, substs) if def.is_struct() => { let mut iter = def .non_enum_variant() @@ -312,12 +286,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> } else { ReducedTy::UnorderedFields(ty) } - } - ty::Adt(def, _) - if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => - { + }, + ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => { ReducedTy::TypeErasure { raw_ptr_only: false } - } + }, // TODO: Check if the conversion to or from at least one of a union's fields is valid. ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false }, @@ -356,11 +328,7 @@ fn same_except_params<'tcx>(subs1: SubstsRef<'tcx>, subs2: SubstsRef<'tcx>) -> b for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) { match (ty1.kind(), ty2.kind()) { (ty::Param(_), _) | (_, ty::Param(_)) => (), - (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) - if adt1 == adt2 && same_except_params(subs1, subs2) => - { - () - } + (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (), _ => return false, } } |