about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-18 22:48:23 +0000
committerbors <bors@rust-lang.org>2022-02-18 22:48:23 +0000
commit29ee5e25d1096f142729ea44c1286e50823762e8 (patch)
tree4cbd60e74ca3f54014ed4b849bbc85cd73d7f502
parent73367f8768f7ebffe3bba9c5b94813c2bb5c045f (diff)
parentd28d19d74cfc94921efa06dffb1d3752d507f9dd (diff)
Auto merge of #8440 - Jarcho:transmute_undefined, r=Manishearth
Some more fixes for `transmute_undefined_repr`

changelog: Fix transmuting a struct containing a pointer into a pointer in `transmute_undefined_repr`
changelog: Allow various forms of type erasure in `transmute_undefined_repr`
-rw-r--r--clippy_lints/src/casts/cast_ptr_alignment.rs18
-rw-r--r--clippy_lints/src/transmute/transmute_undefined_repr.rs109
-rw-r--r--clippy_utils/src/lib.rs1
-rw-r--r--clippy_utils/src/ty.rs14
-rw-r--r--tests/ui/transmute_undefined_repr.rs85
-rw-r--r--tests/ui/transmute_undefined_repr.stderr62
6 files changed, 196 insertions, 93 deletions
diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs
index 079b7ff0675..a4ef1344ab9 100644
--- a/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_hir_ty_cfg_dependant;
+use clippy_utils::ty::is_c_void;
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, GenericArg};
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::sym;
 
 use super::CAST_PTR_ALIGNMENT;
 
@@ -62,19 +62,3 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f
         }
     }
 }
-
-/// Check if the given type is either `core::ffi::c_void` or
-/// one of the platform specific `libc::<platform>::c_void` of libc.
-fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
-    if let ty::Adt(adt, _) = ty.kind() {
-        let names = cx.get_def_path(adt.did);
-
-        if names.is_empty() {
-            return false;
-        }
-        if names[0] == sym::libc || names[0] == sym::core && *names.last().unwrap() == sym!(c_void) {
-            return true;
-        }
-    }
-    false
-}
diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 89439862f69..b6cc1676b00 100644
--- a/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -1,5 +1,6 @@
 use super::TRANSMUTE_UNDEFINED_REPR;
 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::{GenericArg, Subst};
@@ -18,33 +19,55 @@ 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: to_sub_ty,
+            } => match reduce_ty(cx, to_sub_ty) {
+                ReducedTy::IntArray | ReducedTy::TypeErasure => 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;
+                },
             },
-            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: from_sub_ty,
+            } => match reduce_ty(cx, from_sub_ty) {
+                ReducedTy::IntArray | ReducedTy::TypeErasure => 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;
+                },
             },
             ReducedTys::ToPtr {
                 from_ty: from_sub_ty,
@@ -100,7 +123,8 @@ pub(super) fn check<'tcx>(
                 from_ty: from_sub_ty,
                 to_ty: to_sub_ty,
             } => match (reduce_ty(cx, from_sub_ty), reduce_ty(cx, to_sub_ty)) {
-                (ReducedTy::IntArray, _) | (_, ReducedTy::IntArray) => return false,
+                (ReducedTy::IntArray | ReducedTy::TypeErasure, _)
+                | (_, ReducedTy::IntArray | ReducedTy::TypeErasure) => return false,
                 (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => {
                     span_lint_and_then(
                         cx,
@@ -182,13 +206,14 @@ 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> },
 }
 
+/// Remove references so long as both types are references.
 fn reduce_refs<'tcx>(
     cx: &LateContext<'tcx>,
     span: Span,
@@ -208,12 +233,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 }
@@ -227,13 +252,23 @@ fn reduce_refs<'tcx>(
 }
 
 enum ReducedTy<'tcx> {
+    /// The type can be used for type erasure.
+    TypeErasure,
+    /// The type is a struct containing either zero non-zero sized fields, or multiple non-zero
+    /// sized fields with a defined order.
     OrderedFields(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>),
-    Other(Ty<'tcx>),
+    /// The type is an array of a primitive integer type. These can be used as storage for a value
+    /// of another type.
     IntArray,
+    /// Any other type.
+    Other(Ty<'tcx>),
 }
 
+/// Reduce structs containing a single non-zero sized field to it's contained type.
 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);
@@ -243,6 +278,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                 ty = sub_ty;
                 continue;
             },
+            ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure,
             ty::Tuple(args) => {
                 let mut iter = args.iter().map(GenericArg::expect_ty);
                 let Some(sized_ty) = iter.find(|ty| !is_zero_sized_ty(cx, ty)) else {
@@ -261,7 +297,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                     .iter()
                     .map(|f| cx.tcx.type_of(f.did).subst(cx.tcx, substs));
                 let Some(sized_ty) = iter.find(|ty| !is_zero_sized_ty(cx, ty)) else {
-                    return ReducedTy::OrderedFields(ty);
+                    return ReducedTy::TypeErasure;
                 };
                 if iter.all(|ty| is_zero_sized_ty(cx, ty)) {
                     ty = sized_ty;
@@ -273,7 +309,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                     ReducedTy::UnorderedFields(ty)
                 }
             },
-            ty::Ref(..) | ty::RawPtr(_) => ReducedTy::Ref(ty),
+            ty::Adt(def, _) if def.is_enum() && (def.variants.is_empty() || is_c_void(cx, ty)) => {
+                ReducedTy::TypeErasure
+            },
+            ty::Foreign(_) => ReducedTy::TypeErasure,
+            ty::Ref(_, ty, _) => ReducedTy::Ref(ty),
+            ty::RawPtr(ty) => ReducedTy::Ref(ty.ty),
             _ => ReducedTy::Other(ty),
         };
     }
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 73d91550693..5b37a1de8ed 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1,6 +1,7 @@
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(let_else)]
+#![feature(let_chains)]
 #![feature(once_cell)]
 #![feature(rustc_private)]
 #![recursion_limit = "512"]
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 7d74b69906d..6c9ba64525a 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -572,3 +572,17 @@ pub fn get_discriminant_value(tcx: TyCtxt<'_>, adt: &'_ AdtDef, i: VariantIdx) -
         },
     }
 }
+
+/// Check if the given type is either `core::ffi::c_void`, `std::os::raw::c_void`, or one of the
+/// platform specific `libc::<platform>::c_void` types in libc.
+pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
+    if let ty::Adt(adt, _) = ty.kind()
+        && let &[krate, .., name] = &*cx.get_def_path(adt.did)
+        && let sym::libc | sym::core | sym::std = krate
+        && name.as_str() == "c_void"
+    {
+        true
+    } else {
+        false
+    }
+}
diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs
index f0383a03fbd..b163d605634 100644
--- a/tests/ui/transmute_undefined_repr.rs
+++ b/tests/ui/transmute_undefined_repr.rs
@@ -1,5 +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::{size_of, transmute};
 
 fn value<T>() -> T {
     unimplemented!()
@@ -14,35 +17,75 @@ struct Ty2C<T, U>(T, U);
 
 fn main() {
     unsafe {
-        let _: () = core::mem::transmute(value::<Empty>());
-        let _: Empty = core::mem::transmute(value::<()>());
+        let _: () = transmute(value::<Empty>());
+        let _: Empty = transmute(value::<()>());
 
-        let _: Ty<u32> = core::mem::transmute(value::<u32>());
-        let _: Ty<u32> = core::mem::transmute(value::<u32>());
+        let _: Ty<u32> = transmute(value::<u32>());
+        let _: Ty<u32> = transmute(value::<u32>());
 
-        let _: Ty2C<u32, i32> = core::mem::transmute(value::<Ty2<u32, i32>>()); // Lint, Ty2 is unordered
-        let _: Ty2<u32, i32> = core::mem::transmute(value::<Ty2C<u32, i32>>()); // Lint, Ty2 is unordered
+        let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>()); // Lint, Ty2 is unordered
+        let _: Ty2<u32, i32> = transmute(value::<Ty2C<u32, i32>>()); // Lint, Ty2 is unordered
 
-        let _: Ty2<u32, i32> = core::mem::transmute(value::<Ty<Ty2<u32, i32>>>()); // Ok, Ty2 types are the same
-        let _: Ty<Ty2<u32, i32>> = core::mem::transmute(value::<Ty2<u32, i32>>()); // Ok, Ty2 types are the same
+        let _: Ty2<u32, i32> = transmute(value::<Ty<Ty2<u32, i32>>>()); // Ok, Ty2 types are the same
+        let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, i32>>()); // Ok, Ty2 types are the same
 
-        let _: Ty2<u32, f32> = core::mem::transmute(value::<Ty<Ty2<u32, i32>>>()); // Lint, different Ty2 instances
-        let _: Ty<Ty2<u32, i32>> = core::mem::transmute(value::<Ty2<u32, f32>>()); // Lint, different Ty2 instances
+        let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>()); // Lint, different Ty2 instances
+        let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>()); // Lint, different Ty2 instances
 
-        let _: Ty<&()> = core::mem::transmute(value::<&()>());
-        let _: &() = core::mem::transmute(value::<Ty<&()>>());
+        let _: Ty<&()> = transmute(value::<&()>());
+        let _: &() = transmute(value::<Ty<&()>>());
 
-        let _: &Ty2<u32, f32> = core::mem::transmute(value::<Ty<&Ty2<u32, i32>>>()); // Lint, different Ty2 instances
-        let _: Ty<&Ty2<u32, i32>> = core::mem::transmute(value::<&Ty2<u32, f32>>()); // Lint, different Ty2 instances
+        let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>()); // Lint, different Ty2 instances
+        let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>()); // Lint, different Ty2 instances
 
-        let _: Ty<usize> = core::mem::transmute(value::<&Ty2<u32, i32>>()); // Ok, pointer to usize conversion
-        let _: &Ty2<u32, i32> = core::mem::transmute(value::<Ty<usize>>()); // Ok, pointer to usize conversion
+        let _: Ty<usize> = transmute(value::<&Ty2<u32, i32>>()); // Ok, pointer to usize conversion
+        let _: &Ty2<u32, i32> = transmute(value::<Ty<usize>>()); // Ok, pointer to usize conversion
 
-        let _: Ty<[u8; 8]> = core::mem::transmute(value::<Ty2<u32, i32>>()); // Ok, transmute to byte array
-        let _: Ty2<u32, i32> = core::mem::transmute(value::<Ty<[u8; 8]>>()); // Ok, transmute from byte array
+        let _: Ty<[u8; 8]> = transmute(value::<Ty2<u32, i32>>()); // Ok, transmute to byte array
+        let _: Ty2<u32, i32> = transmute(value::<Ty<[u8; 8]>>()); // Ok, transmute from byte array
 
         // issue #8417
-        let _: Ty2C<Ty2<u32, i32>, ()> = core::mem::transmute(value::<Ty2<u32, i32>>()); // Ok, Ty2 types are the same
-        let _: Ty2<u32, i32> = core::mem::transmute(value::<Ty2C<Ty2<u32, i32>, ()>>()); // Ok, Ty2 types are the same
+        let _: Ty2C<Ty2<u32, i32>, ()> = transmute(value::<Ty2<u32, i32>>()); // Ok, Ty2 types are the same
+        let _: Ty2<u32, i32> = transmute(value::<Ty2C<Ty2<u32, i32>, ()>>()); // Ok, Ty2 types are the same
+
+        let _: &'static mut Ty2<u32, u32> = transmute(value::<Box<Ty2<u32, u32>>>()); // Ok, Ty2 types are the same
+        let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32, u32>>()); // Ok, Ty2 types are the same
+        let _: *mut Ty2<u32, u32> = transmute(value::<Box<Ty2<u32, u32>>>()); // Ok, Ty2 types are the same
+        let _: Box<Ty2<u32, u32>> = transmute(value::<*mut Ty2<u32, u32>>()); // Ok, Ty2 types are the same
+
+        let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32, u32>>>()); // Lint, different Ty2 instances
+        let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32, f32>>()); // Lint, different Ty2 instances
+
+        let _: *const () = transmute(value::<Ty<&Ty2<u32, f32>>>()); // Ok, type erasure
+        let _: Ty<&Ty2<u32, f32>> = transmute(value::<*const ()>()); // Ok, reverse type erasure
+
+        let _: *const c_void = transmute(value::<Ty<&Ty2<u32, f32>>>()); // Ok, type erasure
+        let _: Ty<&Ty2<u32, f32>> = transmute(value::<*const c_void>()); // Ok, reverse type erasure
+
+        enum Erase {}
+        let _: *const Erase = transmute(value::<Ty<&Ty2<u32, f32>>>()); // Ok, type erasure
+        let _: Ty<&Ty2<u32, f32>> = transmute(value::<*const Erase>()); // Ok, reverse type erasure
+
+        struct Erase2(
+            [u8; 0],
+            core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
+        );
+        let _: *const Erase2 = transmute(value::<Ty<&Ty2<u32, f32>>>()); // Ok, type erasure
+        let _: Ty<&Ty2<u32, f32>> = 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
+
+        let _: *const [u8] = transmute(value::<Box<[u8]>>()); // Ok
+        let _: Box<[u8]> = transmute(value::<*mut [u8]>()); // Ok
     }
 }
diff --git a/tests/ui/transmute_undefined_repr.stderr b/tests/ui/transmute_undefined_repr.stderr
index 040c63c7afa..42d544fc954 100644
--- a/tests/ui/transmute_undefined_repr.stderr
+++ b/tests/ui/transmute_undefined_repr.stderr
@@ -1,44 +1,64 @@
 error: transmute from `Ty2<u32, i32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:23:33
+  --> $DIR/transmute_undefined_repr.rs:26:33
    |
-LL |         let _: Ty2C<u32, i32> = core::mem::transmute(value::<Ty2<u32, i32>>()); // Lint, Ty2 is unordered
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>()); // Lint, Ty2 is unordered
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = 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:24:32
+  --> $DIR/transmute_undefined_repr.rs:27:32
    |
-LL |         let _: Ty2<u32, i32> = core::mem::transmute(value::<Ty2C<u32, i32>>()); // Lint, Ty2 is unordered
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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:29:32
+  --> $DIR/transmute_undefined_repr.rs:32:32
    |
-LL |         let _: Ty2<u32, f32> = core::mem::transmute(value::<Ty<Ty2<u32, i32>>>()); // Lint, different Ty2 instances
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>()); // Lint, different Ty2 instances
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = 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:30:36
+  --> $DIR/transmute_undefined_repr.rs:33:36
    |
-LL |         let _: Ty<Ty2<u32, i32>> = core::mem::transmute(value::<Ty2<u32, f32>>()); // Lint, different Ty2 instances
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>()); // Lint, different Ty2 instances
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
-error: transmute to `&Ty2<u32, f32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:35:33
+error: transmute from `Ty<&Ty2<u32, i32>>` to `&Ty2<u32, f32>`, both of which have an undefined layout
+  --> $DIR/transmute_undefined_repr.rs:38:33
    |
-LL |         let _: &Ty2<u32, f32> = core::mem::transmute(value::<Ty<&Ty2<u32, i32>>>()); // Lint, different Ty2 instances
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>()); // Lint, different Ty2 instances
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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:39:37
+   |
+LL |         let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>()); // Lint, different Ty2 instances
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: two instances of the same generic type (`Ty2`) may have different layouts
 
-error: transmute from `&Ty2<u32, f32>` which has an undefined layout
-  --> $DIR/transmute_undefined_repr.rs:36:37
+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:56:45
    |
-LL |         let _: Ty<&Ty2<u32, i32>> = core::mem::transmute(value::<&Ty2<u32, f32>>()); // Lint, different Ty2 instances
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32, u32>>>()); // Lint, different Ty2 instances
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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:57:37
+   |
+LL |         let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32, f32>>()); // Lint, different Ty2 instances
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: two instances of the same generic type (`Ty2`) may have different layouts
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors