Skip to content

Commit 75bc5e6

Browse files
committed
basic dyn* support for Miri
1 parent 1397df1 commit 75bc5e6

File tree

5 files changed

+124
-5
lines changed

5 files changed

+124
-5
lines changed

tests/fail/branchless-select-i128-pointer.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
error: Undefined Behavior: constructing invalid value: encountered a dangling reference (address $HEX is unallocated)
1+
error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
22
--> $DIR/branchless-select-i128-pointer.rs:LL:CC
33
|
44
LL | / transmute::<_, &str>(
55
LL | |
66
LL | | !mask & transmute::<_, TwoPtrs>("false !")
77
LL | | | mask & transmute::<_, TwoPtrs>("true !"),
88
LL | | )
9-
| |_____________^ constructing invalid value: encountered a dangling reference (address $HEX is unallocated)
9+
| |_____________^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
1010
|
1111
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
1212
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/fail/validity/dangling_ref1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
use std::mem;
44

55
fn main() {
6-
let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR: encountered a dangling reference (address 0x10 is unallocated)
6+
let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR: encountered a dangling reference
77
}

tests/fail/validity/dangling_ref1.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: constructing invalid value: encountered a dangling reference (address 0x10 is unallocated)
1+
error: Undefined Behavior: constructing invalid value: encountered a dangling reference (0x10[noalloc] has no provenance)
22
--> $DIR/dangling_ref1.rs:LL:CC
33
|
44
LL | let _x: &i32 = unsafe { mem::transmute(16usize) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x10 is unallocated)
5+
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x10[noalloc] has no provenance)
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/pass/dyn-star.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Dyn* handling leads to some funky reentrancy in Stacked Borrows, for some reason
2+
//@compile-flags: -Zmiri-disable-stacked-borrows
3+
#![feature(dyn_star)]
4+
#![allow(incomplete_features)]
5+
6+
use std::fmt::{Debug, Display};
7+
8+
fn main() {
9+
make_dyn_star();
10+
method();
11+
box_();
12+
dispatch_on_pin_mut();
13+
dyn_star_to_dyn();
14+
dyn_to_dyn_star();
15+
}
16+
17+
fn dyn_star_to_dyn() {
18+
let x: dyn* Debug = &42;
19+
let x = Box::new(x) as Box<dyn Debug>;
20+
assert_eq!("42", format!("{x:?}"));
21+
}
22+
23+
fn dyn_to_dyn_star() {
24+
let x: Box<dyn Debug> = Box::new(42);
25+
let x = &x as dyn* Debug;
26+
assert_eq!("42", format!("{x:?}"));
27+
}
28+
29+
fn make_dyn_star() {
30+
fn make_dyn_star_coercion(i: usize) {
31+
let _dyn_i: dyn* Debug = i;
32+
}
33+
34+
fn make_dyn_star_explicit(i: usize) {
35+
let _dyn_i: dyn* Debug = i as dyn* Debug;
36+
}
37+
38+
make_dyn_star_coercion(42);
39+
make_dyn_star_explicit(42);
40+
}
41+
42+
fn method() {
43+
trait Foo {
44+
fn get(&self) -> usize;
45+
}
46+
47+
impl Foo for usize {
48+
fn get(&self) -> usize {
49+
*self
50+
}
51+
}
52+
53+
fn invoke_dyn_star(i: dyn* Foo) -> usize {
54+
i.get()
55+
}
56+
57+
fn make_and_invoke_dyn_star(i: usize) -> usize {
58+
let dyn_i: dyn* Foo = i;
59+
invoke_dyn_star(dyn_i)
60+
}
61+
62+
assert_eq!(make_and_invoke_dyn_star(42), 42);
63+
}
64+
65+
fn box_() {
66+
fn make_dyn_star() -> dyn* Display {
67+
Box::new(42) as dyn* Display
68+
}
69+
70+
let x = make_dyn_star();
71+
assert_eq!(format!("{x}"), "42");
72+
}
73+
74+
fn dispatch_on_pin_mut() {
75+
use std::future::Future;
76+
77+
async fn foo(f: dyn* Future<Output = i32>) {
78+
println!("dispatch_on_pin_mut: value: {}", f.await);
79+
}
80+
81+
async fn async_main() {
82+
foo(Box::pin(async { 1 })).await
83+
}
84+
85+
// ------------------------------------------------------------------------- //
86+
// Implementation Details Below...
87+
88+
use std::pin::Pin;
89+
use std::task::*;
90+
91+
pub fn noop_waker() -> Waker {
92+
let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
93+
94+
// SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
95+
unsafe { Waker::from_raw(raw) }
96+
}
97+
98+
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
99+
100+
unsafe fn noop_clone(_p: *const ()) -> RawWaker {
101+
RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
102+
}
103+
104+
unsafe fn noop(_p: *const ()) {}
105+
106+
let mut fut = async_main();
107+
108+
// Poll loop, just to test the future...
109+
let waker = noop_waker();
110+
let ctx = &mut Context::from_waker(&waker);
111+
112+
loop {
113+
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
114+
Poll::Pending => {}
115+
Poll::Ready(()) => break,
116+
}
117+
}
118+
}

tests/pass/dyn-star.stdout

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dispatch_on_pin_mut: value: 1

0 commit comments

Comments
 (0)