about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-03-25 03:37:12 +0100
committerGitHub <noreply@github.com>2023-03-25 03:37:12 +0100
commit31df7f1ecd2860cf1d38c4b616e9485aa08f110a (patch)
tree4fed1a7629322b0e78c34f97749a71a83a90258f
parent3b49ad3814ba36d55273ab0a0dba085b8953c960 (diff)
parentc2fddfd8e256855c11529b79a4987b2137590f90 (diff)
downloadrust-31df7f1ecd2860cf1d38c4b616e9485aa08f110a.tar.gz
rust-31df7f1ecd2860cf1d38c4b616e9485aa08f110a.zip
Rollup merge of #109568 - RalfJung:miri-raw-ptr-dyn, r=oli-obk
miri: fix raw pointer dyn receivers

r? `@oli-obk`
Fixes https://github.com/rust-lang/miri/issues/2786
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs10
-rw-r--r--src/tools/miri/tests/pass/dyn-arbitrary-self.rs27
2 files changed, 36 insertions, 1 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index c2d1bc11c37..fc83985eaca 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -539,7 +539,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let mut receiver = args[0].clone();
                 let receiver_place = loop {
                     match receiver.layout.ty.kind() {
-                        ty::Ref(..) | ty::RawPtr(..) => break self.deref_operand(&receiver)?,
+                        ty::Ref(..) | ty::RawPtr(..) => {
+                            // We do *not* use `deref_operand` here: we don't want to conceptually
+                            // create a place that must be dereferenceable, since the receiver might
+                            // be a raw pointer and (for `*const dyn Trait`) we don't need to
+                            // actually access memory to resolve this method.
+                            // Also see <https://github.com/rust-lang/miri/issues/2786>.
+                            let val = self.read_immediate(&receiver)?;
+                            break self.ref_to_mplace(&val)?;
+                        }
                         ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
                         ty::Dynamic(.., ty::DynStar) => {
                             // Not clear how to handle this, so far we assume the receiver is always a pointer.
diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
index 94cf465e884..fc58775a195 100644
--- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
+++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
@@ -123,8 +123,35 @@ fn pointers_and_wrappers() {
     assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
 }
 
+fn raw_ptr_receiver() {
+    use std::ptr;
+
+    trait Foo {
+        fn foo(self: *const Self) -> &'static str;
+    }
+
+    impl Foo for i32 {
+        fn foo(self: *const Self) -> &'static str {
+            "I'm an i32!"
+        }
+    }
+
+    impl Foo for u32 {
+        fn foo(self: *const Self) -> &'static str {
+            "I'm a u32!"
+        }
+    }
+
+    let null_i32 = ptr::null::<i32>() as *const dyn Foo;
+    let null_u32 = ptr::null::<u32>() as *const dyn Foo;
+
+    assert_eq!("I'm an i32!", null_i32.foo());
+    assert_eq!("I'm a u32!", null_u32.foo());
+}
+
 fn main() {
     pin_box_dyn();
     stdlib_pointers();
     pointers_and_wrappers();
+    raw_ptr_receiver();
 }