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