about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs14
-rw-r--r--tests/mir-opt/issue_120925_unsafefncast.rs25
2 files changed, 34 insertions, 5 deletions
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 8d4afd5b5dc..370f0db72cb 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -561,9 +561,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                         .ok()?;
                     dest.into()
                 }
-                CastKind::FnPtrToPtr
-                | CastKind::PtrToPtr
-                | CastKind::PointerCoercion(
+                CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
+                    let src = self.evaluated[value].as_ref()?;
+                    let src = self.ecx.read_immediate(src).ok()?;
+                    let to = self.ecx.layout_of(to).ok()?;
+                    let ret = self.ecx.ptr_to_ptr(&src, to).ok()?;
+                    ret.into()
+                }
+                CastKind::PointerCoercion(
                     ty::adjustment::PointerCoercion::MutToConstPointer
                     | ty::adjustment::PointerCoercion::ArrayToPointer
                     | ty::adjustment::PointerCoercion::UnsafeFnPointer,
@@ -571,8 +576,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     let src = self.evaluated[value].as_ref()?;
                     let src = self.ecx.read_immediate(src).ok()?;
                     let to = self.ecx.layout_of(to).ok()?;
-                    let ret = self.ecx.ptr_to_ptr(&src, to).ok()?;
-                    ret.into()
+                    ImmTy::from_immediate(*src, to).into()
                 }
                 _ => return None,
             },
diff --git a/tests/mir-opt/issue_120925_unsafefncast.rs b/tests/mir-opt/issue_120925_unsafefncast.rs
new file mode 100644
index 00000000000..f80ae66efda
--- /dev/null
+++ b/tests/mir-opt/issue_120925_unsafefncast.rs
@@ -0,0 +1,25 @@
+// Verify that we do not ICE when attempting to interpret casts between fn types.
+// skip-filecheck
+
+static FOO: fn() = || assert_ne!(42, 43);
+static BAR: fn(i32, i32) = |a, b| assert_ne!(a, b);
+
+fn main() {
+    FOO();
+
+    let bar: unsafe fn(i32, i32) = BAR;
+
+    let f: fn() = || {};
+    f();
+
+    f();
+
+    f();
+
+    let g: fn(i32) = |i| assert_eq!(i, 2);
+    g(2);
+
+    g(2);
+
+    g(2);
+}