about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2023-02-24 18:32:52 -0800
committerScott McMurray <scottmcm@users.noreply.github.com>2023-03-22 15:15:41 -0700
commit64cce5fc7d2c1070adeaa719932b4bbccf27dd46 (patch)
tree918975145ee82f7777d722aedea9cc75f218dcce /tests
parenta266f11990d9544ee408e213e1eec8cc9eb032b7 (diff)
downloadrust-64cce5fc7d2c1070adeaa719932b4bbccf27dd46.tar.gz
rust-64cce5fc7d2c1070adeaa719932b4bbccf27dd46.zip
Add `CastKind::Transmute` to MIR
Updates `interpret`, `codegen_ssa`, and `codegen_cranelift` to consume the new cast instead of the intrinsic.

Includes `CastTransmute` for custom MIR building, to be able to test the extra UB.
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen/intrinsics/transmute.rs196
-rw-r--r--tests/codegen/transmute-scalar.rs41
-rw-r--r--tests/mir-opt/const_prop/transmute.from_char.ConstProp.diff15
-rw-r--r--tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.diff23
-rw-r--r--tests/mir-opt/const_prop/transmute.rs61
-rw-r--r--tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.diff22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.diff23
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.diff25
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.diff27
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.diff23
-rw-r--r--tests/mir-opt/const_prop/transmute.valid_char.ConstProp.diff15
-rw-r--r--tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff48
-rw-r--r--tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff4
-rw-r--r--tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.rs33
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff27
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff27
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff29
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff29
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff29
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff22
-rw-r--r--tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff6
-rw-r--r--tests/ui/consts/const-eval/panic-assoc-never-type.rs2
-rw-r--r--tests/ui/consts/const-eval/transmute-size-mismatch.rs24
-rw-r--r--tests/ui/consts/const-eval/transmute-size-mismatch.stderr37
-rw-r--r--tests/ui/consts/const-eval/ub-enum.32bit.stderr4
-rw-r--r--tests/ui/consts/const-eval/ub-enum.64bit.stderr4
-rw-r--r--tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr2
-rw-r--r--tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr2
-rw-r--r--tests/ui/statics/uninhabited-static.stderr4
36 files changed, 772 insertions, 82 deletions
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
new file mode 100644
index 00000000000..cefcf9ed9ca
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -0,0 +1,196 @@
+// compile-flags: -O -C no-prepopulate-passes
+// only-64bit (so I don't need to worry about usize)
+// min-llvm-version: 15.0 # this test assumes `ptr`s
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+#![feature(custom_mir)]
+#![feature(inline_const)]
+
+use std::mem::transmute;
+
+// Some of the cases here are statically rejected by `mem::transmute`, so
+// we need to generate custom MIR for those cases to get to codegen.
+use std::intrinsics::mir::*;
+
+enum Never {}
+
+#[repr(align(2))]
+pub struct BigNever(Never, u16, Never);
+
+#[repr(align(8))]
+pub struct Scalar64(i64);
+
+#[repr(C, align(4))]
+pub struct Aggregate64(u16, u8, i8, f32);
+
+// CHECK-LABEL: @check_bigger_size(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_bigger_size(x: u16) -> u32 {
+    // CHECK: call void @llvm.trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_smaller_size(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_smaller_size(x: u32) -> u16 {
+    // CHECK: call void @llvm.trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_to_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
+    // CHECK: call void @llvm.trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_from_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
+    // CHECK: call void @llvm.trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_to_newtype(
+#[no_mangle]
+pub unsafe fn check_to_newtype(x: u64) -> Scalar64 {
+    // CHECK: %0 = alloca i64
+    // CHECK: store i64 %x, ptr %0
+    // CHECK: %1 = load i64, ptr %0
+    // CHECK: ret i64 %1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_newtype(
+#[no_mangle]
+pub unsafe fn check_from_newtype(x: Scalar64) -> u64 {
+    // CHECK: %0 = alloca i64
+    // CHECK: store i64 %x, ptr %0
+    // CHECK: %1 = load i64, ptr %0
+    // CHECK: ret i64 %1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_to_pair(
+#[no_mangle]
+pub unsafe fn check_to_pair(x: u64) -> Option<i32> {
+    // CHECK: %0 = alloca { i32, i32 }, align 4
+    // CHECK: store i64 %x, ptr %0, align 4
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_pair(
+#[no_mangle]
+pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
+    // The two arguments are of types that are only 4-aligned, but they're
+    // immediates so we can write using the destination alloca's alignment.
+    const { assert!(std::mem::align_of::<Option<i32>>() == 4) };
+
+    // CHECK: %0 = alloca i64, align 8
+    // CHECK: store i32 %x.0, ptr %1, align 8
+    // CHECK: store i32 %x.1, ptr %2, align 4
+    // CHECK: %3 = load i64, ptr %0, align 8
+    // CHECK: ret i64 %3
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_to_float(
+#[no_mangle]
+pub unsafe fn check_to_float(x: u32) -> f32 {
+    // CHECK: %0 = alloca float
+    // CHECK: store i32 %x, ptr %0
+    // CHECK: %1 = load float, ptr %0
+    // CHECK: ret float %1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_float(
+#[no_mangle]
+pub unsafe fn check_from_float(x: f32) -> u32 {
+    // CHECK: %0 = alloca i32
+    // CHECK: store float %x, ptr %0
+    // CHECK: %1 = load i32, ptr %0
+    // CHECK: ret i32 %1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_to_bytes(
+#[no_mangle]
+pub unsafe fn check_to_bytes(x: u32) -> [u8; 4] {
+    // CHECK: %0 = alloca [4 x i8], align 1
+    // CHECK: store i32 %x, ptr %0, align 1
+    // CHECK: %1 = load i32, ptr %0, align 1
+    // CHECK: ret i32 %1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_bytes(
+#[no_mangle]
+pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 {
+    // CHECK: %1 = alloca i32, align 4
+    // CHECK: %x = alloca [4 x i8], align 1
+    // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %1, ptr align 1 %x, i64 4, i1 false)
+    // CHECK: %3 = load i32, ptr %1, align 4
+    // CHECK: ret i32 %3
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_to_aggregate(
+#[no_mangle]
+pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 {
+    // CHECK: %0 = alloca %Aggregate64, align 4
+    // CHECK: store i64 %x, ptr %0, align 4
+    // CHECK: %1 = load i64, ptr %0, align 4
+    // CHECK: ret i64 %1
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_from_aggregate(
+#[no_mangle]
+pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 {
+    // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %{{[0-9]+}}, ptr align 4 %x, i64 8, i1 false)
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_long_array_less_aligned(
+#[no_mangle]
+pub unsafe fn check_long_array_less_aligned(x: [u64; 100]) -> [u16; 400] {
+    // CHECK-NEXT: start
+    // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %0, ptr align 8 %x, i64 800, i1 false)
+    // CHECK-NEXT: ret void
+    transmute(x)
+}
+
+// CHECK-LABEL: @check_long_array_more_aligned(
+#[no_mangle]
+pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] {
+    // CHECK-NEXT: start
+    // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 1 %x, i64 100, i1 false)
+    // CHECK-NEXT: ret void
+    transmute(x)
+}
diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs
index 260dcbac0fc..4d7a80bfbe5 100644
--- a/tests/codegen/transmute-scalar.rs
+++ b/tests/codegen/transmute-scalar.rs
@@ -1,13 +1,19 @@
 // compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 # this test assumes `ptr`s and thus no `pointercast`s
 
 #![crate_type = "lib"]
 
-// FIXME(eddyb) all of these tests show memory stores and loads, even after a
-// scalar `bitcast`, more special-casing is required to remove `alloca` usage.
+// With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type,
+// without needing to pointercast, and SRoA will turn that into a `bitcast`.
+// As such, there's no longer special-casing in `transmute` to attempt to
+// generate `bitcast` ourselves, as that just made the IR longer.
+
+// FIXME: That said, `bitcast`s could still be a valuable addition if they could
+// be done in `rvalue_creates_operand`, and thus avoid the `alloca`s entirely.
 
 // CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float noundef %x)
-// CHECK: store i32 %{{.*}}, {{.*}} %0
-// CHECK-NEXT: %[[RES:.*]] = load i32, {{.*}} %0
+// CHECK: store float %{{.*}}, ptr %0
+// CHECK-NEXT: %[[RES:.*]] = load i32, ptr %0
 // CHECK: ret i32 %[[RES]]
 #[no_mangle]
 pub fn f32_to_bits(x: f32) -> u32 {
@@ -25,12 +31,10 @@ pub fn bool_to_byte(b: bool) -> u8 {
 }
 
 // CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 noundef %byte)
-// CHECK: %1 = trunc i8 %byte to i1
-// CHECK-NEXT: %2 = zext i1 %1 to i8
-// CHECK-NEXT: store i8 %2, {{.*}} %0
-// CHECK-NEXT: %3 = load i8, {{.*}} %0
-// CHECK-NEXT: %4 = trunc i8 %3 to i1
-// CHECK: ret i1 %4
+// CHECK: store i8 %byte, ptr %0
+// CHECK-NEXT: %1 = load i8, {{.*}} %0
+// CHECK-NEXT: %2 = trunc i8 %1 to i1
+// CHECK: ret i1 %2
 #[no_mangle]
 pub unsafe fn byte_to_bool(byte: u8) -> bool {
     std::mem::transmute(byte)
@@ -45,20 +49,8 @@ pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
     unsafe { std::mem::transmute(p) }
 }
 
-// HACK(eddyb) scalar `transmute`s between pointers and non-pointers are
-// currently not special-cased like other scalar `transmute`s, because
-// LLVM requires specifically `ptrtoint`/`inttoptr` instead of `bitcast`.
-//
-// Tests below show the non-special-cased behavior (with the possible
-// future special-cased instructions in the "NOTE(eddyb)" comments).
-
 // CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int({{i16\*|ptr}} noundef %p)
-
-// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
-//        %2 = ptrtoint i16* %p to [[USIZE]]
-//             store [[USIZE]] %2, [[USIZE]]* %0
 // CHECK: store {{i16\*|ptr}} %p, {{.*}}
-
 // CHECK-NEXT: %[[RES:.*]] = load [[USIZE]], {{.*}} %0
 // CHECK: ret [[USIZE]] %[[RES]]
 #[no_mangle]
@@ -67,12 +59,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize {
 }
 
 // CHECK: define{{.*}}{{i16\*|ptr}} @int_to_ptr([[USIZE]] noundef %i)
-
-// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
-//        %2 = inttoptr [[USIZE]] %i to i16*
-//             store i16* %2, i16** %0
 // CHECK: store [[USIZE]] %i, {{.*}}
-
 // CHECK-NEXT: %[[RES:.*]] = load {{i16\*|ptr}}, {{.*}} %0
 // CHECK: ret {{i16\*|ptr}} %[[RES]]
 #[no_mangle]
diff --git a/tests/mir-opt/const_prop/transmute.from_char.ConstProp.diff b/tests/mir-opt/const_prop/transmute.from_char.ConstProp.diff
new file mode 100644
index 00000000000..933dfbb5166
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.from_char.ConstProp.diff
@@ -0,0 +1,15 @@
+- // MIR for `from_char` before ConstProp
++ // MIR for `from_char` after ConstProp
+  
+  fn from_char() -> i32 {
+      let mut _0: i32;                     // return place in scope 0 at $DIR/transmute.rs:+0:23: +0:26
+      scope 1 {
+      }
+  
+      bb0: {
+-         _0 = const 'R' as i32 (Transmute); // scope 1 at $DIR/transmute.rs:+1:14: +1:28
++         _0 = const 82_i32;               // scope 1 at $DIR/transmute.rs:+1:14: +1:28
+          return;                          // scope 0 at $DIR/transmute.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.diff b/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.diff
new file mode 100644
index 00000000000..f3474855f02
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.invalid_bool.ConstProp.diff
@@ -0,0 +1,14 @@
+- // MIR for `invalid_bool` before ConstProp
++ // MIR for `invalid_bool` after ConstProp
+  
+  fn invalid_bool() -> bool {
+      let mut _0: bool;                    // return place in scope 0 at $DIR/transmute.rs:+0:33: +0:37
+      scope 1 {
+      }
+  
+      bb0: {
+          _0 = const -1_i8 as bool (Transmute); // scope 1 at $DIR/transmute.rs:+1:14: +1:30
+          return;                          // scope 0 at $DIR/transmute.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.diff b/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.diff
new file mode 100644
index 00000000000..ba087e226c9
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.invalid_char.ConstProp.diff
@@ -0,0 +1,14 @@
+- // MIR for `invalid_char` before ConstProp
++ // MIR for `invalid_char` after ConstProp
+  
+  fn invalid_char() -> char {
+      let mut _0: char;                    // return place in scope 0 at $DIR/transmute.rs:+0:33: +0:37
+      scope 1 {
+      }
+  
+      bb0: {
+          _0 = const _ as char (Transmute); // scope 1 at $DIR/transmute.rs:+1:14: +1:33
+          return;                          // scope 0 at $DIR/transmute.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.diff b/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.diff
new file mode 100644
index 00000000000..76d464789c1
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.less_as_i8.ConstProp.diff
@@ -0,0 +1,23 @@
+- // MIR for `less_as_i8` before ConstProp
++ // MIR for `less_as_i8` after ConstProp
+  
+  fn less_as_i8() -> i8 {
+      let mut _0: i8;                      // return place in scope 0 at $DIR/transmute.rs:+0:24: +0:26
+      let mut _1: std::cmp::Ordering;      // in scope 0 at $DIR/transmute.rs:+1:24: +1:48
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 1 at $DIR/transmute.rs:+1:24: +1:48
+-         _1 = Less;                       // scope 1 at $DIR/transmute.rs:+1:24: +1:48
+-         _0 = move _1 as i8 (Transmute);  // scope 1 at $DIR/transmute.rs:+1:14: +1:49
++         _1 = const Less;                 // scope 1 at $DIR/transmute.rs:+1:24: +1:48
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: std::cmp::Ordering, val: Value(Scalar(0xff)) }
++         _0 = const -1_i8;                // scope 1 at $DIR/transmute.rs:+1:14: +1:49
+          StorageDead(_1);                 // scope 1 at $DIR/transmute.rs:+1:48: +1:49
+          return;                          // scope 0 at $DIR/transmute.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.rs b/tests/mir-opt/const_prop/transmute.rs
new file mode 100644
index 00000000000..b753cdccd60
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.rs
@@ -0,0 +1,61 @@
+// unit-test: ConstProp
+// compile-flags: -O --crate-type=lib
+
+use std::mem::transmute;
+
+// EMIT_MIR transmute.less_as_i8.ConstProp.diff
+pub fn less_as_i8() -> i8 {
+    unsafe { transmute(std::cmp::Ordering::Less) }
+}
+
+// EMIT_MIR transmute.from_char.ConstProp.diff
+pub fn from_char() -> i32 {
+    unsafe { transmute('R') }
+}
+
+// EMIT_MIR transmute.valid_char.ConstProp.diff
+pub fn valid_char() -> char {
+    unsafe { transmute(0x52_u32) }
+}
+
+// EMIT_MIR transmute.invalid_char.ConstProp.diff
+pub unsafe fn invalid_char() -> char {
+    unsafe { transmute(i32::MAX) }
+}
+
+// EMIT_MIR transmute.invalid_bool.ConstProp.diff
+pub unsafe fn invalid_bool() -> bool {
+    unsafe { transmute(-1_i8) }
+}
+
+// EMIT_MIR transmute.undef_union_as_integer.ConstProp.diff
+pub unsafe fn undef_union_as_integer() -> u32 {
+    union Union32 { value: u32, unit: () }
+    unsafe { transmute(Union32 { unit: () }) }
+}
+
+// EMIT_MIR transmute.unreachable_direct.ConstProp.diff
+pub unsafe fn unreachable_direct() -> ! {
+    let x: Never = unsafe { transmute(()) };
+    match x {}
+}
+
+// EMIT_MIR transmute.unreachable_ref.ConstProp.diff
+pub unsafe fn unreachable_ref() -> ! {
+    let x: &Never = unsafe { transmute(1_usize) };
+    match *x {}
+}
+
+// EMIT_MIR transmute.unreachable_mut.ConstProp.diff
+pub unsafe fn unreachable_mut() -> ! {
+    let x: &mut Never = unsafe { transmute(1_usize) };
+    match *x {}
+}
+
+// EMIT_MIR transmute.unreachable_box.ConstProp.diff
+pub unsafe fn unreachable_box() -> ! {
+    let x: Box<Never> = unsafe { transmute(1_usize) };
+    match *x {}
+}
+
+enum Never {}
diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.diff
new file mode 100644
index 00000000000..538b1f26e4c
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.ConstProp.diff
@@ -0,0 +1,22 @@
+- // MIR for `undef_union_as_integer` before ConstProp
++ // MIR for `undef_union_as_integer` after ConstProp
+  
+  fn undef_union_as_integer() -> u32 {
+      let mut _0: u32;                     // return place in scope 0 at $DIR/transmute.rs:+0:43: +0:46
+      let mut _1: undef_union_as_integer::Union32; // in scope 0 at $DIR/transmute.rs:+2:24: +2:44
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+2:40: +2:42
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 1 at $DIR/transmute.rs:+2:24: +2:44
+          StorageLive(_2);                 // scope 1 at $DIR/transmute.rs:+2:40: +2:42
+          _2 = ();                         // scope 1 at $DIR/transmute.rs:+2:40: +2:42
+          _1 = Union32 { value: move _2 }; // scope 1 at $DIR/transmute.rs:+2:24: +2:44
+          StorageDead(_2);                 // scope 1 at $DIR/transmute.rs:+2:43: +2:44
+          _0 = move _1 as u32 (Transmute); // scope 1 at $DIR/transmute.rs:+2:14: +2:45
+          StorageDead(_1);                 // scope 1 at $DIR/transmute.rs:+2:44: +2:45
+          return;                          // scope 0 at $DIR/transmute.rs:+3:2: +3:2
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.diff
new file mode 100644
index 00000000000..8bf97996a67
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.diff
@@ -0,0 +1,23 @@
+- // MIR for `unreachable_box` before ConstProp
++ // MIR for `unreachable_box` after ConstProp
+  
+  fn unreachable_box() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
+      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
+      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+      }
+      scope 2 {
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.diff
new file mode 100644
index 00000000000..81b7b368993
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.diff
@@ -0,0 +1,25 @@
+- // MIR for `unreachable_direct` before ConstProp
++ // MIR for `unreachable_direct` after ConstProp
+  
+  fn unreachable_direct() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
+      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
+      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
+      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+      }
+      scope 2 {
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.diff
new file mode 100644
index 00000000000..34f7aea8ed2
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.diff
@@ -0,0 +1,27 @@
+- // MIR for `unreachable_mut` before ConstProp
++ // MIR for `unreachable_mut` after ConstProp
+  
+  fn unreachable_mut() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
+      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
+      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
+      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+      }
+      scope 2 {
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
+          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.diff
new file mode 100644
index 00000000000..ff95f2a0b94
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.diff
@@ -0,0 +1,23 @@
+- // MIR for `unreachable_ref` before ConstProp
++ // MIR for `unreachable_ref` after ConstProp
+  
+  fn unreachable_ref() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
+      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
+      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+      }
+      scope 2 {
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
+      }
+  }
+  
diff --git a/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.diff b/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.diff
new file mode 100644
index 00000000000..eac33b73003
--- /dev/null
+++ b/tests/mir-opt/const_prop/transmute.valid_char.ConstProp.diff
@@ -0,0 +1,15 @@
+- // MIR for `valid_char` before ConstProp
++ // MIR for `valid_char` after ConstProp
+  
+  fn valid_char() -> char {
+      let mut _0: char;                    // return place in scope 0 at $DIR/transmute.rs:+0:24: +0:28
+      scope 1 {
+      }
+  
+      bb0: {
+-         _0 = const 82_u32 as char (Transmute); // scope 1 at $DIR/transmute.rs:+1:14: +1:33
++         _0 = const 'R';                  // scope 1 at $DIR/transmute.rs:+1:14: +1:33
+          return;                          // scope 0 at $DIR/transmute.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
index bcda1288045..8e6e6fc0ec2 100644
--- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
+++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -24,61 +24,49 @@
           StorageLive(_2);                 // scope 0 at $DIR/issue_75439.rs:+2:9: +2:15
           StorageLive(_3);                 // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52
           _3 = _1;                         // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52
-          _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53
-                                           // mir::Constant
-                                           // + span: $DIR/issue_75439.rs:8:37: 8:46
-                                           // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(<ZST>) }
+          _2 = move _3 as [u32; 4] (Transmute); // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53
+          StorageDead(_3);                 // scope 2 at $DIR/issue_75439.rs:+2:52: +2:53
+          switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb6]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb1: {
-          StorageDead(_3);                 // scope 2 at $DIR/issue_75439.rs:+2:52: +2:53
-          switchInt(_2[0 of 4]) -> [0: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb6]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb2: {
-          switchInt(_2[1 of 4]) -> [0: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[2 of 4]) -> [0: bb4, 4294901760: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb3: {
-          switchInt(_2[2 of 4]) -> [0: bb5, 4294901760: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
-      }
-  
-      bb4: {
           StorageLive(_5);                 // scope 3 at $DIR/issue_75439.rs:+5:14: +5:38
           StorageLive(_6);                 // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35
           _6 = _4;                         // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35
-          _5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36
-                                           // mir::Constant
-                                           // + span: $DIR/issue_75439.rs:11:23: 11:32
-                                           // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::<u32, [u8; 4]>}, val: Value(<ZST>) }
+          _5 = move _6 as [u8; 4] (Transmute); // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36
+          StorageDead(_6);                 // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36
+          _0 = Option::<[u8; 4]>::Some(move _5); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
+          StorageDead(_5);                 // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39
+          StorageDead(_4);                 // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6
+          goto -> bb7;                     // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
       }
   
-      bb5: {
+      bb4: {
           StorageLive(_4);                 // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29
           _4 = _2[3 of 4];                 // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29
-          goto -> bb4;                     // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          goto -> bb3;                     // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
-      bb6: {
+      bb5: {
           StorageLive(_4);                 // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29
           _4 = _2[3 of 4];                 // scope 3 at $DIR/issue_75439.rs:+4:27: +4:29
-          goto -> bb4;                     // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          goto -> bb3;                     // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
-      bb7: {
-          StorageDead(_6);                 // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36
-          _0 = Option::<[u8; 4]>::Some(move _5); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
-          StorageDead(_5);                 // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39
-          StorageDead(_4);                 // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6
-          goto -> bb9;                     // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
-      }
-  
-      bb8: {
+      bb6: {
           _0 = Option::<[u8; 4]>::None;    // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
-          goto -> bb9;                     // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
+          goto -> bb7;                     // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
       }
   
-      bb9: {
+      bb7: {
           StorageDead(_2);                 // scope 0 at $DIR/issue_75439.rs:+9:1: +9:2
           return;                          // scope 0 at $DIR/issue_75439.rs:+9:2: +9:2
       }
diff --git a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
index d9898d8e0f0..5c5a9e90a9d 100644
--- a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
           StorageLive(_1);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
 -         _1 = std::intrinsics::assume(const true) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:72:9: 72:32
+-                                          // + span: $DIR/lower_intrinsics.rs:105:9: 105:32
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value(<ZST>) }
 +         assume(const true);              // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
 +         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index d962ef8cb12..87960521bb4 100644
--- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -31,7 +31,7 @@
           _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
 -         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:49:5: 49:41
+-                                          // + span: $DIR/lower_intrinsics.rs:82:5: 82:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) }
 +         _2 = discriminant((*_3));        // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
@@ -46,13 +46,13 @@
           StorageLive(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
           _19 = const _;                   // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:50:42: 50:44
+                                           // + span: $DIR/lower_intrinsics.rs:83:42: 83:44
                                            // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
 -         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:50:5: 50:41
+-                                          // + span: $DIR/lower_intrinsics.rs:83:5: 83:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) }
 +         _5 = discriminant((*_6));        // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
 +         goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
@@ -67,13 +67,13 @@
           StorageLive(_11);                // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
           _18 = const _;                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:51:42: 51:45
+                                           // + span: $DIR/lower_intrinsics.rs:84:42: 84:45
                                            // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
 -         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:51:5: 51:41
+-                                          // + span: $DIR/lower_intrinsics.rs:84:5: 84:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) }
 +         _9 = discriminant((*_10));       // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
 +         goto -> bb3;                     // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
@@ -88,13 +88,13 @@
           StorageLive(_15);                // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
           _17 = const _;                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:52:42: 52:47
+                                           // + span: $DIR/lower_intrinsics.rs:85:42: 85:47
                                            // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
 -         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:52:5: 52:41
+-                                          // + span: $DIR/lower_intrinsics.rs:85:5: 85:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) }
 +         _13 = discriminant((*_14));      // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
 +         goto -> bb4;                     // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
index 5c972a00e46..15cce7f4a2c 100644
--- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
@@ -49,7 +49,7 @@
           StorageDead(_9);                 // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91
 -         _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:65:9: 65:28
+-                                          // + span: $DIR/lower_intrinsics.rs:98:9: 98:28
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::<i32>}, val: Value(<ZST>) }
 +         copy_nonoverlapping(dst = move _8, src = move _4, count = const 0_usize); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
 +         goto -> bb1;                     // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
diff --git a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
index e535141e772..c563703b250 100644
--- a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
@@ -24,7 +24,7 @@
           _4 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56
 -         _3 = option_payload_ptr::<usize>(move _4) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:99:18: 99:54
+-                                          // + span: $DIR/lower_intrinsics.rs:132:18: 132:54
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<usize>) -> *const usize {option_payload_ptr::<usize>}, val: Value(<ZST>) }
 +         _3 = &raw const (((*_4) as Some).0: usize); // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
 +         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
@@ -37,7 +37,7 @@
           _6 = &raw const (*_2);           // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56
 -         _5 = option_payload_ptr::<String>(move _6) -> bb2; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:100:18: 100:54
+-                                          // + span: $DIR/lower_intrinsics.rs:133:18: 133:54
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<String>) -> *const String {option_payload_ptr::<String>}, val: Value(<ZST>) }
 +         _5 = &raw const (((*_6) as Some).0: std::string::String); // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
 +         goto -> bb2;                     // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
index 27fceeedf6e..f2f676843b2 100644
--- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
           _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
 -         _0 = read_via_copy::<i32>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:85:14: 85:45
+-                                          // + span: $DIR/lower_intrinsics.rs:118:14: 118:45
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32) -> i32 {read_via_copy::<i32>}, val: Value(<ZST>) }
 +         _0 = (*_2);                      // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 +         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
index 610c67d2fec..3ad21283fa4 100644
--- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
           _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
 -         _0 = read_via_copy::<Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:90:14: 90:45
+-                                          // + span: $DIR/lower_intrinsics.rs:123:14: 123:45
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Never) -> Never {read_via_copy::<Never>}, val: Value(<ZST>) }
 +         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
       }
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index f07e2816f4f..ec215c9a664 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -38,6 +38,39 @@ pub fn non_const<T>() -> usize {
     size_of_t()
 }
 
+// EMIT_MIR lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
+pub fn transmute_inhabited(c: std::cmp::Ordering) -> i8 {
+    unsafe { std::mem::transmute(c) }
+}
+
+// EMIT_MIR lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
+pub unsafe fn transmute_uninhabited(u: ()) -> Never {
+    unsafe { std::mem::transmute::<(), Never>(u) }
+}
+
+// EMIT_MIR lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
+pub unsafe fn transmute_ref_dst<T: ?Sized>(u: &T) -> *const T {
+    unsafe { std::mem::transmute(u) }
+}
+
+// EMIT_MIR lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
+pub unsafe fn transmute_to_ref_uninhabited() -> ! {
+    let x: &Never = std::mem::transmute(1usize);
+    match *x {}
+}
+
+// EMIT_MIR lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
+pub unsafe fn transmute_to_mut_uninhabited() -> ! {
+    let x: &mut Never = std::mem::transmute(1usize);
+    match *x {}
+}
+
+// EMIT_MIR lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
+pub unsafe fn transmute_to_box_uninhabited() -> ! {
+    let x: Box<Never> = std::mem::transmute(1usize);
+    match *x {}
+}
+
 pub enum E {
     A,
     B,
diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
new file mode 100644
index 00000000000..814368ec021
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
@@ -0,0 +1,27 @@
+- // MIR for `transmute_inhabited` before LowerIntrinsics
++ // MIR for `transmute_inhabited` after LowerIntrinsics
+  
+  fn transmute_inhabited(_1: std::cmp::Ordering) -> i8 {
+      debug c => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:28: +0:29
+      let mut _0: i8;                      // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:54: +0:56
+      let mut _2: std::cmp::Ordering;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+-         _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:43:14: 43:33
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(std::cmp::Ordering) -> i8 {transmute::<std::cmp::Ordering, i8>}, val: Value(<ZST>) }
++         _0 = move _2 as i8 (Transmute);  // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
++         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+      }
+  
+      bb1: {
+          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:35: +1:36
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
new file mode 100644
index 00000000000..5440c7a4c8e
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
@@ -0,0 +1,27 @@
+- // MIR for `transmute_ref_dst` before LowerIntrinsics
++ // MIR for `transmute_ref_dst` after LowerIntrinsics
+  
+  fn transmute_ref_dst(_1: &T) -> *const T {
+      debug u => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:44: +0:45
+      let mut _0: *const T;                // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:54: +0:62
+      let mut _2: &T;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+-         _0 = transmute::<&T, *const T>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:53:14: 53:33
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&T) -> *const T {transmute::<&T, *const T>}, val: Value(<ZST>) }
++         _0 = move _2 as *const T (Transmute); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
++         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+      }
+  
+      bb1: {
+          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:35: +1:36
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
new file mode 100644
index 00000000000..43ddccc1ef7
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
@@ -0,0 +1,29 @@
+- // MIR for `transmute_to_box_uninhabited` before LowerIntrinsics
++ // MIR for `transmute_to_box_uninhabited` after LowerIntrinsics
+  
+  fn transmute_to_box_uninhabited() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
+      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
+      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _2 = transmute::<usize, Box<Never>>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:70:25: 70:44
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box<Never> {transmute::<usize, Box<Never>>}, val: Value(<ZST>) }
++         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+      }
+  
+      bb1: {
+          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+          unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
new file mode 100644
index 00000000000..bf529a9ca67
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
@@ -0,0 +1,29 @@
+- // MIR for `transmute_to_mut_uninhabited` before LowerIntrinsics
++ // MIR for `transmute_to_mut_uninhabited` after LowerIntrinsics
+  
+  fn transmute_to_mut_uninhabited() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
+      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
+      let _2: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _2 = transmute::<usize, &mut Never>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:64:25: 64:44
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::<usize, &mut Never>}, val: Value(<ZST>) }
++         _2 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+      }
+  
+      bb1: {
+          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+          unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
new file mode 100644
index 00000000000..4940a99021f
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
@@ -0,0 +1,29 @@
+- // MIR for `transmute_to_ref_uninhabited` before LowerIntrinsics
++ // MIR for `transmute_to_ref_uninhabited` after LowerIntrinsics
+  
+  fn transmute_to_ref_uninhabited() -> ! {
+      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
+      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
+      let _2: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      scope 1 {
+          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _2 = transmute::<usize, &Never>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:58:21: 58:40
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::<usize, &Never>}, val: Value(<ZST>) }
++         _2 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+      }
+  
+      bb1: {
+          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+          unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
new file mode 100644
index 00000000000..f3a12b9ba5f
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
@@ -0,0 +1,22 @@
+- // MIR for `transmute_uninhabited` before LowerIntrinsics
++ // MIR for `transmute_uninhabited` after LowerIntrinsics
+  
+  fn transmute_uninhabited(_1: ()) -> Never {
+      debug u => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:37: +0:38
+      let mut _0: Never;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:47: +0:52
+      let mut _2: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:47: +1:48
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
+          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
+-         _0 = transmute::<(), Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:48:14: 48:46
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Never {transmute::<(), Never>}, val: Value(<ZST>) }
++         _0 = move _2 as Never (Transmute); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
++         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
index 9870a70dec5..3b9a41249a4 100644
--- a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
@@ -32,7 +32,7 @@
           _5 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
 -         _3 = add_with_overflow::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:78:14: 78:49
+-                                          // + span: $DIR/lower_intrinsics.rs:111:14: 111:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {add_with_overflow::<i32>}, val: Value(<ZST>) }
 +         _3 = CheckedAdd(move _4, move _5); // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
@@ -48,7 +48,7 @@
           _8 = _2;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
 -         _6 = sub_with_overflow::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:79:14: 79:49
+-                                          // + span: $DIR/lower_intrinsics.rs:112:14: 112:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {sub_with_overflow::<i32>}, val: Value(<ZST>) }
 +         _6 = CheckedSub(move _7, move _8); // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
 +         goto -> bb2;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
@@ -64,7 +64,7 @@
           _11 = _2;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
 -         _9 = mul_with_overflow::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:80:14: 80:49
+-                                          // + span: $DIR/lower_intrinsics.rs:113:14: 113:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {mul_with_overflow::<i32>}, val: Value(<ZST>) }
 +         _9 = CheckedMul(move _10, move _11); // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
 +         goto -> bb3;                     // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.rs b/tests/ui/consts/const-eval/panic-assoc-never-type.rs
index 28edf514402..1abe708d19e 100644
--- a/tests/ui/consts/const-eval/panic-assoc-never-type.rs
+++ b/tests/ui/consts/const-eval/panic-assoc-never-type.rs
@@ -11,5 +11,5 @@ impl PrintName {
 }
 
 fn main() {
-    let _ = PrintName::VOID; //~ constant
+    let _ = PrintName::VOID; //~ erroneous constant used
 }
diff --git a/tests/ui/consts/const-eval/transmute-size-mismatch.rs b/tests/ui/consts/const-eval/transmute-size-mismatch.rs
new file mode 100644
index 00000000000..2410baea28c
--- /dev/null
+++ b/tests/ui/consts/const-eval/transmute-size-mismatch.rs
@@ -0,0 +1,24 @@
+#![feature(core_intrinsics)]
+#![feature(custom_mir)]
+
+// These cases are statically rejected by `mem::transmute`, so we need custom
+// MIR to be able to get to constant evaluation.
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime", phase = "initial")]
+const unsafe fn mir_transmute<T, U>(x: T) -> U {
+    mir!{
+        {
+            RET = CastTransmute(x);
+            //~^ ERROR evaluation of constant value failed
+            //~| ERROR evaluation of constant value failed
+            Return()
+        }
+    }
+}
+
+const FROM_BIGGER: u16 = unsafe { mir_transmute(123_i32) };
+
+const FROM_SMALLER: u32 = unsafe { mir_transmute(123_i16) };
+
+fn main() {}
diff --git a/tests/ui/consts/const-eval/transmute-size-mismatch.stderr b/tests/ui/consts/const-eval/transmute-size-mismatch.stderr
new file mode 100644
index 00000000000..e051491d343
--- /dev/null
+++ b/tests/ui/consts/const-eval/transmute-size-mismatch.stderr
@@ -0,0 +1,37 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/transmute-size-mismatch.rs:12:13
+   |
+LL |             RET = CastTransmute(x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^ transmuting from 4-byte type to 2-byte type: `i32` -> `u16`
+   |
+note: inside `mir_transmute::<i32, u16>`
+  --> $DIR/transmute-size-mismatch.rs:12:13
+   |
+LL |             RET = CastTransmute(x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+note: inside `FROM_BIGGER`
+  --> $DIR/transmute-size-mismatch.rs:20:35
+   |
+LL | const FROM_BIGGER: u16 = unsafe { mir_transmute(123_i32) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/transmute-size-mismatch.rs:12:13
+   |
+LL |             RET = CastTransmute(x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^ transmuting from 2-byte type to 4-byte type: `i16` -> `u32`
+   |
+note: inside `mir_transmute::<i16, u32>`
+  --> $DIR/transmute-size-mismatch.rs:12:13
+   |
+LL |             RET = CastTransmute(x);
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+note: inside `FROM_SMALLER`
+  --> $DIR/transmute-size-mismatch.rs:22:36
+   |
+LL | const FROM_SMALLER: u32 = unsafe { mir_transmute(123_i16) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ub-enum.32bit.stderr b/tests/ui/consts/const-eval/ub-enum.32bit.stderr
index 2d86bd88f1c..3ad1ac974c8 100644
--- a/tests/ui/consts/const-eval/ub-enum.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.32bit.stderr
@@ -108,13 +108,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:96:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
 
 error: aborting due to 13 previous errors
 
diff --git a/tests/ui/consts/const-eval/ub-enum.64bit.stderr b/tests/ui/consts/const-eval/ub-enum.64bit.stderr
index a89d7ec5f6d..a66706d1af9 100644
--- a/tests/ui/consts/const-eval/ub-enum.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.64bit.stderr
@@ -108,13 +108,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:96:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
 
 error: aborting due to 13 previous errors
 
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index 231005d7e39..74bc6317c80 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -11,7 +11,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:4:14
    |
 LL |     unsafe { std::mem::transmute(()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of the never type `!`
    |
 note: inside `foo`
   --> $DIR/validate_uninhabited_zsts.rs:4:14
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index 231005d7e39..74bc6317c80 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -11,7 +11,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:4:14
    |
 LL |     unsafe { std::mem::transmute(()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of the never type `!`
    |
 note: inside `foo`
   --> $DIR/validate_uninhabited_zsts.rs:4:14
diff --git a/tests/ui/statics/uninhabited-static.stderr b/tests/ui/statics/uninhabited-static.stderr
index 437053a4476..35fdcae6a59 100644
--- a/tests/ui/statics/uninhabited-static.stderr
+++ b/tests/ui/statics/uninhabited-static.stderr
@@ -47,7 +47,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/uninhabited-static.rs:12:31
    |
 LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Void
 
 warning: the type `Void` does not permit zero-initialization
   --> $DIR/uninhabited-static.rs:12:31
@@ -66,7 +66,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/uninhabited-static.rs:16:32
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Void
 
 warning: the type `Void` does not permit zero-initialization
   --> $DIR/uninhabited-static.rs:16:32