about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/transmute/transmute_undefined_repr.rs397
-rw-r--r--tests/ui/transmute_undefined_repr.rs4
-rw-r--r--tests/ui/transmute_undefined_repr.stderr24
3 files changed, 195 insertions, 230 deletions
diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs
index bf1cfb859bc..b6d7d9f5b42 100644
--- a/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -5,9 +5,9 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
-use rustc_span::Span;
+use rustc_span::DUMMY_SP;
 
-#[allow(clippy::too_many_lines)]
+#[expect(clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     e: &'tcx Expr<'_>,
@@ -18,116 +18,89 @@ pub(super) fn check<'tcx>(
     let mut to_ty = cx.tcx.erase_regions(to_ty_orig);
 
     while from_ty != to_ty {
-        match reduce_refs(cx, e.span, from_ty, to_ty) {
-            ReducedTys::FromFatPtr {
-                unsized_ty,
-                to_ty: to_sub_ty,
-            } => match reduce_ty(cx, to_sub_ty) {
-                ReducedTy::TypeErasure => break,
-                ReducedTy::UnorderedFields(ty) if is_size_pair(ty) => break,
-                ReducedTy::Ref(to_sub_ty) => {
-                    from_ty = unsized_ty;
-                    to_ty = to_sub_ty;
-                    continue;
-                },
-                _ => {
-                    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;
-                },
+        let reduced_tys = reduce_refs(cx, from_ty, to_ty);
+        match (reduce_ty(cx, reduced_tys.from_ty), reduce_ty(cx, reduced_tys.to_ty)) {
+            // Various forms of type erasure.
+            (ReducedTy::TypeErasure { raw_ptr_only: false }, _)
+            | (_, ReducedTy::TypeErasure { raw_ptr_only: false }) => return false,
+            (ReducedTy::TypeErasure { .. }, _) if reduced_tys.from_raw_ptr => return false,
+            (_, ReducedTy::TypeErasure { .. }) if reduced_tys.to_raw_ptr => return false,
+
+            // `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))) => {
+                from_ty = from_sub_ty;
+                to_ty = to_sub_ty;
+                continue;
             },
-            ReducedTys::ToFatPtr {
-                unsized_ty,
-                from_ty: from_sub_ty,
-            } => match reduce_ty(cx, from_sub_ty) {
-                ReducedTy::TypeErasure => break,
-                ReducedTy::UnorderedFields(ty) if is_size_pair(ty) => break,
-                ReducedTy::Ref(from_sub_ty) => {
-                    from_ty = from_sub_ty;
-                    to_ty = unsized_ty;
-                    continue;
-                },
-                _ => {
-                    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;
-                },
+            (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;
             },
-            ReducedTys::ToPtr {
-                from_ty: from_sub_ty,
-                to_ty: to_sub_ty,
-            } => match reduce_ty(cx, from_sub_ty) {
-                ReducedTy::UnorderedFields(from_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() != from_ty {
-                                diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
-                            }
-                        },
-                    );
-                    return true;
-                },
-                ReducedTy::Ref(from_sub_ty) => {
-                    from_ty = from_sub_ty;
-                    to_ty = to_sub_ty;
-                    continue;
-                },
-                _ => break,
+            (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;
             },
-            ReducedTys::FromPtr {
-                from_ty: from_sub_ty,
-                to_ty: to_sub_ty,
-            } => match reduce_ty(cx, to_sub_ty) {
-                ReducedTy::UnorderedFields(to_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() != to_ty {
-                                diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
-                            }
-                        },
-                    );
-                    return true;
-                },
-                ReducedTy::Ref(to_sub_ty) => {
-                    from_ty = from_sub_ty;
-                    to_ty = to_sub_ty;
-                    continue;
-                },
-                _ => break,
+
+            // ptr <-> ptr
+            (ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty))
+                if matches!(from_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_))
+                    && matches!(to_sub_ty.kind(), ty::Ref(..) | ty::RawPtr(_)) =>
+            {
+                from_ty = from_sub_ty;
+                to_ty = to_sub_ty;
+                continue;
             },
-            ReducedTys::Other {
-                from_ty: from_sub_ty,
-                to_ty: to_sub_ty,
-            } => match (reduce_ty(cx, from_sub_ty), reduce_ty(cx, to_sub_ty)) {
-                (ReducedTy::TypeErasure, _) | (_, ReducedTy::TypeErasure) => return false,
-                (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))
+
+            // 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 => {
+                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() != from_ty.peel_refs() {
+                            diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+                        }
+                    },
+                );
+                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),
+                    |diag| {
+                        if to_ty_orig.peel_refs() != to_ty.peel_refs() {
+                            diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+                        }
+                    },
+                );
+                return true;
+            },
+
+            (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
                     {
@@ -138,83 +111,72 @@ pub(super) fn check<'tcx>(
                     } else {
                         None
                     };
-                    span_lint_and_then(
-                        cx,
-                        TRANSMUTE_UNDEFINED_REPR,
-                        e.span,
-                        &format!(
-                            "transmute from `{}` to `{}`, both of which have an undefined layout",
-                            from_ty_orig, to_ty_orig
-                        ),
-                        |diag| {
-                            if let Some(same_adt_did) = same_adt_did {
-                                diag.note(&format!(
-                                    "two instances of the same generic type (`{}`) may have different layouts",
-                                    cx.tcx.item_name(same_adt_did)
-                                ));
-                            } else {
-                                if from_ty_orig.peel_refs() != from_ty {
-                                    diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
-                                }
-                                if to_ty_orig.peel_refs() != to_ty {
-                                    diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
-                                }
-                            }
-                        },
-                    );
-                    return true;
-                },
-                // `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::Ref(from_sub_ty), ReducedTy::Ref(to_sub_ty)) => {
-                    from_ty = from_sub_ty;
-                    to_ty = to_sub_ty;
-                    continue;
-                },
-                (
-                    ReducedTy::UnorderedFields(from_ty),
-                    ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::Ref(_),
-                ) => {
-                    span_lint_and_then(
-                        cx,
-                        TRANSMUTE_UNDEFINED_REPR,
-                        e.span,
-                        &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
-                        |diag| {
+                span_lint_and_then(
+                    cx,
+                    TRANSMUTE_UNDEFINED_REPR,
+                    e.span,
+                    &format!(
+                        "transmute from `{}` to `{}`, both of which have an undefined layout",
+                        from_ty_orig, to_ty_orig
+                    ),
+                    |diag| {
+                        if let Some(same_adt_did) = same_adt_did {
+                            diag.note(&format!(
+                                "two instances of the same generic type (`{}`) may have different layouts",
+                                cx.tcx.item_name(same_adt_did)
+                            ));
+                        } else {
                             if from_ty_orig.peel_refs() != from_ty {
                                 diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
                             }
-                        },
-                    );
-                    return true;
-                },
-                (
-                    ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::Ref(_),
-                    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),
-                        |diag| {
                             if to_ty_orig.peel_refs() != to_ty {
                                 diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
                             }
-                        },
-                    );
-                    return true;
-                },
-                (
-                    ReducedTy::OrderedFields(..) | ReducedTy::Ref(_) | ReducedTy::Other(_) | ReducedTy::Param,
-                    ReducedTy::OrderedFields(..) | ReducedTy::Ref(_) | ReducedTy::Other(_) | ReducedTy::Param,
-                )
-                | (
-                    ReducedTy::UnorderedFields(_) | ReducedTy::Param,
-                    ReducedTy::UnorderedFields(_) | ReducedTy::Param,
-                ) => break,
+                        }
+                    },
+                );
+                return true;
+            },
+            (
+                ReducedTy::UnorderedFields(from_ty),
+                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),
+                    |diag| {
+                        if from_ty_orig.peel_refs() != from_ty {
+                            diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+                        }
+                    },
+                );
+                return 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),
+                    |diag| {
+                        if to_ty_orig.peel_refs() != to_ty {
+                            diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+                        }
+                    },
+                );
+                return 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;
             },
         }
     }
@@ -222,65 +184,64 @@ pub(super) fn check<'tcx>(
     false
 }
 
-enum ReducedTys<'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> },
+#[expect(clippy::struct_excessive_bools)]
+struct ReducedTys<'tcx> {
+    from_ty: Ty<'tcx>,
+    to_ty: Ty<'tcx>,
+    from_raw_ptr: bool,
+    to_raw_ptr: bool,
+    from_fat_ptr: bool,
+    to_fat_ptr: bool,
 }
 
 /// Remove references so long as both types are references.
-fn reduce_refs<'tcx>(
-    cx: &LateContext<'tcx>,
-    span: Span,
-    mut from_ty: Ty<'tcx>,
-    mut to_ty: Ty<'tcx>,
-) -> ReducedTys<'tcx> {
-    loop {
-        return match (from_ty.kind(), to_ty.kind()) {
+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(span), cx.param_env) =>
+                if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
             {
-                ReducedTys::FromFatPtr { unsized_ty, to_ty }
+                (true, false)
             },
             (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })))
-                if !unsized_ty.is_sized(cx.tcx.at(span), cx.param_env) =>
+                if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
             {
-                ReducedTys::ToFatPtr { unsized_ty, from_ty }
+                (false, true)
             },
-            (&(ty::Ref(_, from_ty, _) | ty::RawPtr(TypeAndMut { ty: from_ty, .. })), _) => {
-                ReducedTys::FromPtr { from_ty, to_ty }
-            },
-            (_, &(ty::Ref(_, to_ty, _) | ty::RawPtr(TypeAndMut { ty: to_ty, .. }))) => {
-                ReducedTys::ToPtr { from_ty, to_ty }
-            },
-            _ => ReducedTys::Other { from_ty, to_ty },
+            _ => (false, false),
         };
+    };
+    ReducedTys {
+        from_ty,
+        to_ty,
+        from_raw_ptr,
+        to_raw_ptr,
+        from_fat_ptr,
+        to_fat_ptr,
     }
 }
 
 enum ReducedTy<'tcx> {
     /// The type can be used for type erasure.
-    TypeErasure,
+    TypeErasure { raw_ptr_only: bool },
     /// The type is a struct containing either zero non-zero sized fields, or multiple non-zero
     /// sized fields with a defined order.
     /// The second value is the first non-zero sized type.
     OrderedFields(Ty<'tcx>, Option<Ty<'tcx>>),
     /// The type is a struct containing multiple non-zero sized fields with no defined order.
     UnorderedFields(Ty<'tcx>),
-    /// The type is a reference to the contained type.
-    Ref(Ty<'tcx>),
-    /// The type is a generic parameter.
-    Param,
     /// Any other type.
     Other(Ty<'tcx>),
 }
@@ -290,12 +251,14 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
     loop {
         ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty);
         return match *ty.kind() {
-            ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => ReducedTy::TypeErasure,
+            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,
+            ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false },
             ty::Tuple(args) => {
                 let mut iter = args.iter();
                 let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
@@ -314,7 +277,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                     .iter()
                     .map(|f| cx.tcx.bound_type_of(f.did).subst(cx.tcx, substs));
                 let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
-                    return ReducedTy::TypeErasure;
+                    return ReducedTy::TypeErasure { raw_ptr_only: false };
                 };
                 if iter.all(|ty| is_zero_sized_ty(cx, ty)) {
                     ty = sized_ty;
@@ -327,14 +290,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                 }
             },
             ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => {
-                ReducedTy::TypeErasure
+                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,
-            ty::Foreign(_) => ReducedTy::TypeErasure,
-            ty::Ref(_, ty, _) => ReducedTy::Ref(ty),
-            ty::RawPtr(ty) => ReducedTy::Ref(ty.ty),
-            ty::Param(_) => ReducedTy::Param,
+            ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false },
+            ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false },
+            ty::Int(_) | ty::Uint(_) => ReducedTy::TypeErasure { raw_ptr_only: true },
             _ => ReducedTy::Other(ty),
         };
     }
diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs
index 6df8ed8feea..5aad0b44270 100644
--- a/tests/ui/transmute_undefined_repr.rs
+++ b/tests/ui/transmute_undefined_repr.rs
@@ -4,6 +4,7 @@
 use core::any::TypeId;
 use core::ffi::c_void;
 use core::mem::{size_of, transmute, MaybeUninit};
+use core::ptr::NonNull;
 
 fn value<T>() -> T {
     unimplemented!()
@@ -117,6 +118,9 @@ fn main() {
 
         let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty2<u32, u32>>>()); // Err
         let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const Ty2<u32, u32>>()); // Err
+
+        let _: NonNull<u8> = transmute(value::<NonNull<(String, String)>>()); // Ok
+        let _: NonNull<(String, String)> = transmute(value::<NonNull<u8>>()); // Ok
     }
 }
 
diff --git a/tests/ui/transmute_undefined_repr.stderr b/tests/ui/transmute_undefined_repr.stderr
index 8319f71a83d..e50a773290e 100644
--- a/tests/ui/transmute_undefined_repr.stderr
+++ b/tests/ui/transmute_undefined_repr.stderr
@@ -1,5 +1,5 @@
 error: transmute from `Ty2<u32, i32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:27:33
+  --> $DIR/transmute_undefined_repr.rs:28:33
    |
 LL |         let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>()); // Lint, Ty2 is unordered
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,13 +7,13 @@ LL |         let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>()); // Lin
    = note: `-D clippy::transmute-undefined-repr` implied by `-D warnings`
 
 error: transmute into `Ty2<u32, i32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:28:32
+  --> $DIR/transmute_undefined_repr.rs:29:32
    |
 LL |         let _: Ty2<u32, i32> = transmute(value::<Ty2C<u32, i32>>()); // Lint, Ty2 is unordered
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `Ty<Ty2<u32, i32>>` to `Ty2<u32, f32>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:33:32
+  --> $DIR/transmute_undefined_repr.rs:34:32
    |
 LL |         let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>()); // Lint, different Ty2 instances
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL |         let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>()); //
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `Ty2<u32, f32>` to `Ty<Ty2<u32, i32>>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:34:36
+  --> $DIR/transmute_undefined_repr.rs:35:36
    |
 LL |         let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>()); // Lint, different Ty2 instances
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL |         let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>()); //
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `Ty<&Ty2<u32, i32>>` to `&Ty2<u32, f32>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:39:33
+  --> $DIR/transmute_undefined_repr.rs:40:33
    |
 LL |         let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>()); // Lint, different Ty2 instances
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL |         let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>()); /
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `&Ty2<u32, f32>` to `Ty<&Ty2<u32, i32>>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:40:37
+  --> $DIR/transmute_undefined_repr.rs:41:37
    |
 LL |         let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>()); // Lint, different Ty2 instances
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |         let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>()); /
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `std::boxed::Box<Ty2<u32, u32>>` to `&mut Ty2<u32, f32>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:57:45
+  --> $DIR/transmute_undefined_repr.rs:58:45
    |
 LL |         let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32, u32>>>()); // Lint, different Ty2 instances
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL |         let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32,
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `&mut Ty2<u32, f32>` to `std::boxed::Box<Ty2<u32, u32>>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:58:37
+  --> $DIR/transmute_undefined_repr.rs:59:37
    |
 LL |         let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32, f32>>()); // Lint, different Ty2 instances
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL |         let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32,
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute into `*const Ty2<u32, u32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:118:39
+  --> $DIR/transmute_undefined_repr.rs:119:39
    |
 LL |         let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty2<u32, u32>>>()); // Err
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL |         let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty
    = note: the contained type `Ty2<u32, u32>` has an undefined layout
 
 error: transmute from `*const Ty2<u32, u32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:119:50
+  --> $DIR/transmute_undefined_repr.rs:120:50
    |
 LL |         let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const Ty2<u32, u32>>()); // Err
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |         let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const T
    = note: the contained type `Ty2<u32, u32>` has an undefined layout
 
 error: transmute from `std::vec::Vec<Ty2<U, i32>>` to `std::vec::Vec<Ty2<T, u32>>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:146:35
+  --> $DIR/transmute_undefined_repr.rs:150:35
    |
 LL |         let _: Vec<Ty2<T, u32>> = transmute(value::<Vec<Ty2<U, i32>>>()); // Err
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -85,7 +85,7 @@ LL |         let _: Vec<Ty2<T, u32>> = transmute(value::<Vec<Ty2<U, i32>>>()); /
    = note: two instances of the same generic type (`Vec`) may have different layouts
 
 error: transmute from `std::vec::Vec<Ty2<T, u32>>` to `std::vec::Vec<Ty2<U, i32>>`, both of which have an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:147:35
+  --> $DIR/transmute_undefined_repr.rs:151:35
    |
 LL |         let _: Vec<Ty2<U, i32>> = transmute(value::<Vec<Ty2<T, u32>>>()); // Err
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^