summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs178
1 files changed, 104 insertions, 74 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 b6d7d9f5b..3d4bbbf64 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
@@ -3,9 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_c_void;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
-use rustc_span::DUMMY_SP;
#[expect(clippy::too_many_lines)]
pub(super) fn check<'tcx>(
@@ -28,24 +27,32 @@ 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))
@@ -55,19 +62,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 => {
@@ -75,31 +82,37 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
+ &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 `{}` has an undefined layout", from_ty));
+ 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,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute to `{}` which has an undefined layout", to_ty_orig),
+ &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 `{}` has an undefined layout", to_ty));
+ 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
@@ -116,8 +129,7 @@ pub(super) fn check<'tcx>(
TRANSMUTE_UNDEFINED_REPR,
e.span,
&format!(
- "transmute from `{}` to `{}`, both of which have an undefined layout",
- from_ty_orig, to_ty_orig
+ "transmute from `{from_ty_orig}` to `{to_ty_orig}`, both of which have an undefined layout"
),
|diag| {
if let Some(same_adt_did) = same_adt_did {
@@ -127,57 +139,73 @@ pub(super) fn check<'tcx>(
));
} else {
if from_ty_orig.peel_refs() != from_ty {
- diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+ 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 `{}` has an undefined layout", to_ty));
+ 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,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
+ &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 `{}` has an undefined layout", from_ty));
+ 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(
cx,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute into `{}` which has an undefined layout", to_ty_orig),
+ &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 `{}` has an undefined layout", to_ty));
+ 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;
- },
+ }
}
}
@@ -195,42 +223,38 @@ 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.at(DUMMY_SP), cx.param_env) =>
- {
- (true, false)
- },
- (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })))
- if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), 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> {
@@ -253,11 +277,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();
@@ -269,7 +293,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()
@@ -288,10 +312,12 @@ 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 },
@@ -330,7 +356,11 @@ 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,
}
}