diff options
| author | bors <bors@rust-lang.org> | 2023-02-21 04:22:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-02-21 04:22:23 +0000 |
| commit | f715e430aac0de131e2ad21804013ea405722a66 (patch) | |
| tree | 939698b73a07d4fb71bc0a27a9c8e0054986d42f /src | |
| parent | 2deff71719a32af76eb4493ddb1dc4653fb88cad (diff) | |
| parent | 054c76d6580eb84139cb619c3dff8865828a9fbc (diff) | |
| download | rust-f715e430aac0de131e2ad21804013ea405722a66.tar.gz rust-f715e430aac0de131e2ad21804013ea405722a66.zip | |
Auto merge of #107728 - RalfJung:miri-dyn-star, r=RalfJung,oli-obk
Miri: basic dyn* support As usual I am very unsure about the dynamic dispatch stuff, but it passes even the `Pin<&mut dyn* Trait>` test so that is something. TBH I think it was a mistake to make `dyn Trait` and `dyn* Trait` part of the same `TyKind` variant. Almost everywhere in Miri this lead to the wrong default behavior, resulting in strange ICEs instead of nice "unimplemented" messages. The two types describe pretty different runtime data layout after all. Strangely I did not need to do the equivalent of [this diff](https://github.com/rust-lang/rust/pull/106532#discussion_r1087095963) in Miri. Maybe that is because the unsizing logic matches on `ty::Dynamic(.., ty::Dyn)` already? In `unsized_info` I don't think the `target_dyn_kind` can be `DynStar`, since then it wouldn't be unsized! r? `@oli-obk` Cc `@eholk` (dyn-star) https://github.com/rust-lang/rust/issues/102425
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/miri/src/helpers.rs | 4 | ||||
| -rw-r--r-- | src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr | 4 | ||||
| -rw-r--r-- | src/tools/miri/tests/fail/validity/dangling_ref1.rs | 2 | ||||
| -rw-r--r-- | src/tools/miri/tests/fail/validity/dangling_ref1.stderr | 4 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/dyn-star.rs | 116 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/dyn-star.stdout | 1 |
6 files changed, 126 insertions, 5 deletions
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 5286023e0f6..ed3dd741a8b 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -478,6 +478,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } else if matches!(v.layout.fields, FieldsShape::Union(..)) { // A (non-frozen) union. We fall back to whatever the type says. (self.unsafe_cell_action)(v) + } else if matches!(v.layout.ty.kind(), ty::Dynamic(_, _, ty::DynStar)) { + // This needs to read the vtable pointer to proceed type-driven, but we don't + // want to reentrantly read from memory here. + (self.unsafe_cell_action)(v) } else { // We want to not actually read from memory for this visit. So, before // walking this value, we have to make sure it is not a diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr b/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr index 96f2ff3282c..d68b4b8dfc6 100644 --- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr +++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value: encountered a dangling reference (address $HEX is unallocated) +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) --> $DIR/branchless-select-i128-pointer.rs:LL:CC | LL | / transmute::<_, &str>( @@ -6,7 +6,7 @@ LL | | LL | | !mask & transmute::<_, TwoPtrs>("false !") LL | | | mask & transmute::<_, TwoPtrs>("true !"), LL | | ) - | |_____________^ constructing invalid value: encountered a dangling reference (address $HEX is unallocated) + | |_____________^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.rs b/src/tools/miri/tests/fail/validity/dangling_ref1.rs index 6bf2d9295a3..fc3a9f34463 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref1.rs +++ b/src/tools/miri/tests/fail/validity/dangling_ref1.rs @@ -3,5 +3,5 @@ use std::mem; fn main() { - let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR: encountered a dangling reference (address 0x10 is unallocated) + let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR: encountered a dangling reference } diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.stderr b/src/tools/miri/tests/fail/validity/dangling_ref1.stderr index 01ef071e869..830ab9ca501 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref1.stderr +++ b/src/tools/miri/tests/fail/validity/dangling_ref1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: constructing invalid value: encountered a dangling reference (address 0x10 is unallocated) +error: Undefined Behavior: constructing invalid value: encountered a dangling reference (0x10[noalloc] has no provenance) --> $DIR/dangling_ref1.rs:LL:CC | LL | let _x: &i32 = unsafe { mem::transmute(16usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x10 is unallocated) + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x10[noalloc] has no provenance) | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/pass/dyn-star.rs b/src/tools/miri/tests/pass/dyn-star.rs new file mode 100644 index 00000000000..16a8cec6cda --- /dev/null +++ b/src/tools/miri/tests/pass/dyn-star.rs @@ -0,0 +1,116 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::{Debug, Display}; + +fn main() { + make_dyn_star(); + method(); + box_(); + dispatch_on_pin_mut(); + dyn_star_to_dyn(); + dyn_to_dyn_star(); +} + +fn dyn_star_to_dyn() { + let x: dyn* Debug = &42; + let x = Box::new(x) as Box<dyn Debug>; + assert_eq!("42", format!("{x:?}")); +} + +fn dyn_to_dyn_star() { + let x: Box<dyn Debug> = Box::new(42); + let x = &x as dyn* Debug; + assert_eq!("42", format!("{x:?}")); +} + +fn make_dyn_star() { + fn make_dyn_star_coercion(i: usize) { + let _dyn_i: dyn* Debug = i; + } + + fn make_dyn_star_explicit(i: usize) { + let _dyn_i: dyn* Debug = i as dyn* Debug; + } + + make_dyn_star_coercion(42); + make_dyn_star_explicit(42); +} + +fn method() { + trait Foo { + fn get(&self) -> usize; + } + + impl Foo for usize { + fn get(&self) -> usize { + *self + } + } + + fn invoke_dyn_star(i: dyn* Foo) -> usize { + i.get() + } + + fn make_and_invoke_dyn_star(i: usize) -> usize { + let dyn_i: dyn* Foo = i; + invoke_dyn_star(dyn_i) + } + + assert_eq!(make_and_invoke_dyn_star(42), 42); +} + +fn box_() { + fn make_dyn_star() -> dyn* Display { + Box::new(42) as dyn* Display + } + + let x = make_dyn_star(); + assert_eq!(format!("{x}"), "42"); +} + +fn dispatch_on_pin_mut() { + use std::future::Future; + + async fn foo(f: dyn* Future<Output = i32>) { + println!("dispatch_on_pin_mut: value: {}", f.await); + } + + async fn async_main() { + foo(Box::pin(async { 1 })).await + } + + // ------------------------------------------------------------------------- // + // Implementation Details Below... + + use std::pin::Pin; + use std::task::*; + + pub fn noop_waker() -> Waker { + let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE); + + // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld + unsafe { Waker::from_raw(raw) } + } + + const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); + + unsafe fn noop_clone(_p: *const ()) -> RawWaker { + RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE) + } + + unsafe fn noop(_p: *const ()) {} + + let mut fut = async_main(); + + // Poll loop, just to test the future... + let waker = noop_waker(); + let ctx = &mut Context::from_waker(&waker); + + loop { + match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { + Poll::Pending => {} + Poll::Ready(()) => break, + } + } +} diff --git a/src/tools/miri/tests/pass/dyn-star.stdout b/src/tools/miri/tests/pass/dyn-star.stdout new file mode 100644 index 00000000000..e94427ee305 --- /dev/null +++ b/src/tools/miri/tests/pass/dyn-star.stdout @@ -0,0 +1 @@ +dispatch_on_pin_mut: value: 1 |
