]> git.lizzy.rs Git - rust.git/blob - src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs
test drop order for parameters when a future is dropped part-way through execution
[rust.git] / src / test / ui / async-await / drop-order / drop-order-when-cancelled.rs
1 // aux-build:arc_wake.rs
2 // edition:2018
3 // run-pass
4
5 #![allow(unused_variables)]
6 #![feature(async_await)]
7
8 // Test that the drop order for parameters in a fn and async fn matches up. Also test that
9 // parameters (used or unused) are not dropped until the async fn is cancelled.
10 // This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs
11
12 extern crate arc_wake;
13
14 use arc_wake::ArcWake;
15 use std::cell::RefCell;
16 use std::future::Future;
17 use std::marker::PhantomData;
18 use std::pin::Pin;
19 use std::rc::Rc;
20 use std::sync::Arc;
21 use std::task::{Context, Poll};
22
23 struct EmptyWaker;
24
25 impl ArcWake for EmptyWaker {
26     fn wake(self: Arc<Self>) {}
27 }
28
29 #[derive(Debug, Eq, PartialEq)]
30 enum DropOrder {
31     Function,
32     Val(&'static str),
33 }
34
35 type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
36
37 struct D(&'static str, DropOrderListPtr);
38
39 impl Drop for D {
40     fn drop(&mut self) {
41         self.1.borrow_mut().push(DropOrder::Val(self.0));
42     }
43 }
44
45 struct NeverReady;
46
47 impl Future for NeverReady {
48     type Output = ();
49     fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
50         Poll::Pending
51     }
52 }
53
54 /// Check that unused bindings are dropped after the function is polled.
55 async fn foo_async(x: D, _y: D) {
56     x.1.borrow_mut().push(DropOrder::Function);
57     NeverReady.await;
58 }
59
60 fn foo_sync(x: D, _y: D) {
61     x.1.borrow_mut().push(DropOrder::Function);
62 }
63
64 /// Check that underscore patterns are dropped after the function is polled.
65 async fn bar_async(x: D, _: D) {
66     x.1.borrow_mut().push(DropOrder::Function);
67     NeverReady.await;
68 }
69
70 fn bar_sync(x: D, _: D) {
71     x.1.borrow_mut().push(DropOrder::Function);
72 }
73
74 /// Check that underscore patterns within more complex patterns are dropped after the function
75 /// is polled.
76 async fn baz_async((x, _): (D, D)) {
77     x.1.borrow_mut().push(DropOrder::Function);
78     NeverReady.await;
79 }
80
81 fn baz_sync((x, _): (D, D)) {
82     x.1.borrow_mut().push(DropOrder::Function);
83 }
84
85 /// Check that underscore and unused bindings within and outwith more complex patterns are dropped
86 /// after the function is polled.
87 async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
88     x.1.borrow_mut().push(DropOrder::Function);
89     NeverReady.await;
90 }
91
92 fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
93     x.1.borrow_mut().push(DropOrder::Function);
94 }
95
96 struct Foo;
97
98 impl Foo {
99     /// Check that unused bindings are dropped after the method is polled.
100     async fn foo_async(x: D, _y: D) {
101         x.1.borrow_mut().push(DropOrder::Function);
102         NeverReady.await;
103     }
104
105     fn foo_sync(x: D, _y: D) {
106         x.1.borrow_mut().push(DropOrder::Function);
107     }
108
109     /// Check that underscore patterns are dropped after the method is polled.
110     async fn bar_async(x: D, _: D) {
111         x.1.borrow_mut().push(DropOrder::Function);
112         NeverReady.await;
113     }
114
115     fn bar_sync(x: D, _: D) {
116         x.1.borrow_mut().push(DropOrder::Function);
117     }
118
119     /// Check that underscore patterns within more complex patterns are dropped after the method
120     /// is polled.
121     async fn baz_async((x, _): (D, D)) {
122         x.1.borrow_mut().push(DropOrder::Function);
123         NeverReady.await;
124     }
125
126     fn baz_sync((x, _): (D, D)) {
127         x.1.borrow_mut().push(DropOrder::Function);
128     }
129
130     /// Check that underscore and unused bindings within and outwith more complex patterns are
131     /// dropped after the method is polled.
132     async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
133         x.1.borrow_mut().push(DropOrder::Function);
134         NeverReady.await;
135     }
136
137     fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
138         x.1.borrow_mut().push(DropOrder::Function);
139     }
140 }
141
142 struct Bar<'a>(PhantomData<&'a ()>);
143
144 impl<'a> Bar<'a> {
145     /// Check that unused bindings are dropped after the method with self is polled.
146     async fn foo_async(&'a self, x: D, _y: D) {
147         x.1.borrow_mut().push(DropOrder::Function);
148         NeverReady.await;
149     }
150
151     fn foo_sync(&'a self, x: D, _y: D) {
152         x.1.borrow_mut().push(DropOrder::Function);
153     }
154
155     /// Check that underscore patterns are dropped after the method with self is polled.
156     async fn bar_async(&'a self, x: D, _: D) {
157         x.1.borrow_mut().push(DropOrder::Function);
158         NeverReady.await;
159     }
160
161     fn bar_sync(&'a self, x: D, _: D) {
162         x.1.borrow_mut().push(DropOrder::Function);
163     }
164
165     /// Check that underscore patterns within more complex patterns are dropped after the method
166     /// with self is polled.
167     async fn baz_async(&'a self, (x, _): (D, D)) {
168         x.1.borrow_mut().push(DropOrder::Function);
169         NeverReady.await;
170     }
171
172     fn baz_sync(&'a self, (x, _): (D, D)) {
173         x.1.borrow_mut().push(DropOrder::Function);
174     }
175
176     /// Check that underscore and unused bindings within and outwith more complex patterns are
177     /// dropped after the method with self is polled.
178     async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
179         x.1.borrow_mut().push(DropOrder::Function);
180         NeverReady.await;
181     }
182
183     fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
184         x.1.borrow_mut().push(DropOrder::Function);
185     }
186 }
187
188 fn assert_drop_order_after_cancel<Fut: Future<Output = ()>>(
189     f: impl FnOnce(DropOrderListPtr) -> Fut,
190     g: impl FnOnce(DropOrderListPtr),
191 ) {
192     let empty = Arc::new(EmptyWaker);
193     let waker = ArcWake::into_waker(empty);
194     let mut cx = Context::from_waker(&waker);
195
196     let actual_order = Rc::new(RefCell::new(Vec::new()));
197     let mut fut = Box::pin(f(actual_order.clone()));
198     let _ = fut.as_mut().poll(&mut cx);
199
200     // Parameters are never dropped until the future completes.
201     assert_eq!(*actual_order.borrow(), vec![DropOrder::Function]);
202     
203     drop(fut);
204
205     let expected_order = Rc::new(RefCell::new(Vec::new()));
206     g(expected_order.clone());
207     assert_eq!(*actual_order.borrow(), *expected_order.borrow());
208 }
209
210 fn main() {
211     // Free functions (see doc comment on function for what it tests).
212     assert_drop_order_after_cancel(
213         |l| foo_async(D("x", l.clone()), D("_y", l.clone())),
214         |l| foo_sync(D("x", l.clone()), D("_y", l.clone())),
215     );
216     assert_drop_order_after_cancel(
217         |l| bar_async(D("x", l.clone()), D("_", l.clone())),
218         |l| bar_sync(D("x", l.clone()), D("_", l.clone())),
219     );
220     assert_drop_order_after_cancel(
221         |l| baz_async((D("x", l.clone()), D("_", l.clone()))),
222         |l| baz_sync((D("x", l.clone()), D("_", l.clone()))),
223     );
224     assert_drop_order_after_cancel(
225         |l| {
226             foobar_async(
227                 D("x", l.clone()),
228                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
229                 D("_", l.clone()),
230                 D("_y", l.clone()),
231             )
232         },
233         |l| {
234             foobar_sync(
235                 D("x", l.clone()),
236                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
237                 D("_", l.clone()),
238                 D("_y", l.clone()),
239             )
240         },
241     );
242
243     // Methods w/out self (see doc comment on function for what it tests).
244     assert_drop_order_after_cancel(
245         |l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
246         |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())),
247     );
248     assert_drop_order_after_cancel(
249         |l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
250         |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())),
251     );
252     assert_drop_order_after_cancel(
253         |l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
254         |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))),
255     );
256     assert_drop_order_after_cancel(
257         |l| {
258             Foo::foobar_async(
259                 D("x", l.clone()),
260                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
261                 D("_", l.clone()),
262                 D("_y", l.clone()),
263             )
264         },
265         |l| {
266             Foo::foobar_sync(
267                 D("x", l.clone()),
268                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
269                 D("_", l.clone()),
270                 D("_y", l.clone()),
271             )
272         },
273     );
274
275     // Methods (see doc comment on function for what it tests).
276     let b = Bar(Default::default());
277     assert_drop_order_after_cancel(
278         |l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
279         |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())),
280     );
281     assert_drop_order_after_cancel(
282         |l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
283         |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())),
284     );
285     assert_drop_order_after_cancel(
286         |l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
287         |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))),
288     );
289     assert_drop_order_after_cancel(
290         |l| {
291             b.foobar_async(
292                 D("x", l.clone()),
293                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
294                 D("_", l.clone()),
295                 D("_y", l.clone()),
296             )
297         },
298         |l| {
299             b.foobar_sync(
300                 D("x", l.clone()),
301                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
302                 D("_", l.clone()),
303                 D("_y", l.clone()),
304             )
305         },
306     );
307 }