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