diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-03-25 03:37:12 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-25 03:37:12 +0100 |
| commit | 31df7f1ecd2860cf1d38c4b616e9485aa08f110a (patch) | |
| tree | 4fed1a7629322b0e78c34f97749a71a83a90258f | |
| parent | 3b49ad3814ba36d55273ab0a0dba085b8953c960 (diff) | |
| parent | c2fddfd8e256855c11529b79a4987b2137590f90 (diff) | |
| download | rust-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.rs | 10 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/dyn-arbitrary-self.rs | 27 |
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(); } |
