diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index c2d1bc11c37b5..fc83985eaca22 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 . + 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 94cf465e884d1..fc58775a195e8 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::() as *const dyn Foo; + let null_u32 = ptr::null::() 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(); }