]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
Auto merge of #103881 - ChayimFriedman2:patch-2, r=compiler-errors
[rust.git] / src / tools / miri / tests / pass / stacked-borrows / future-self-referential.rs
1 #![feature(pin_macro)]
2
3 use std::future::*;
4 use std::marker::PhantomPinned;
5 use std::pin::*;
6 use std::ptr;
7 use std::task::*;
8
9 struct Delay {
10     delay: usize,
11 }
12
13 impl Delay {
14     fn new(delay: usize) -> Self {
15         Delay { delay }
16     }
17 }
18
19 impl Future for Delay {
20     type Output = ();
21     fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
22         if self.delay > 0 {
23             self.delay -= 1;
24             Poll::Pending
25         } else {
26             Poll::Ready(())
27         }
28     }
29 }
30
31 async fn do_stuff() {
32     (&mut Delay::new(1)).await;
33 }
34
35 // Same thing implemented by hand
36 struct DoStuff {
37     state: usize,
38     delay: Delay,
39     delay_ref: *mut Delay,
40     _marker: PhantomPinned,
41 }
42
43 impl DoStuff {
44     fn new() -> Self {
45         DoStuff {
46             state: 0,
47             delay: Delay::new(1),
48             delay_ref: ptr::null_mut(),
49             _marker: PhantomPinned,
50         }
51     }
52 }
53
54 impl Future for DoStuff {
55     type Output = ();
56     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
57         unsafe {
58             let this = self.get_unchecked_mut();
59             match this.state {
60                 0 => {
61                     // Set up self-ref.
62                     this.delay_ref = &mut this.delay;
63                     // Move to next state.
64                     this.state = 1;
65                     Poll::Pending
66                 }
67                 1 => {
68                     let delay = &mut *this.delay_ref;
69                     Pin::new_unchecked(delay).poll(cx)
70                 }
71                 _ => unreachable!(),
72             }
73         }
74     }
75 }
76
77 fn run_fut<T>(fut: impl Future<Output = T>) -> T {
78     use std::sync::Arc;
79
80     struct MyWaker;
81     impl Wake for MyWaker {
82         fn wake(self: Arc<Self>) {
83             unimplemented!()
84         }
85     }
86
87     let waker = Waker::from(Arc::new(MyWaker));
88     let mut context = Context::from_waker(&waker);
89
90     let mut pinned = pin!(fut);
91     loop {
92         match pinned.as_mut().poll(&mut context) {
93             Poll::Pending => continue,
94             Poll::Ready(v) => return v,
95         }
96     }
97 }
98
99 fn main() {
100     run_fut(do_stuff());
101     run_fut(DoStuff::new());
102 }