]> git.lizzy.rs Git - rust.git/blob - src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs
Rollup merge of #60897 - seanmonstar:patch-4, r=sfackler
[rust.git] / src / test / ui / async-await / drop-order / drop-order-for-async-fn-parameters-by-ref-binding.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(ref mut x: D, ref mut _y: D) {
46     x.1.borrow_mut().push(DropOrder::Function);
47 }
48
49 fn foo_sync(ref mut x: D, ref mut _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(ref mut x: D, _: D) {
55     x.1.borrow_mut().push(DropOrder::Function);
56 }
57
58 fn bar_sync(ref mut 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((ref mut x, _): (D, D)) {
65     x.1.borrow_mut().push(DropOrder::Function);
66 }
67
68 fn baz_sync((ref mut 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(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) {
75     x.1.borrow_mut().push(DropOrder::Function);
76 }
77
78 fn foobar_sync(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _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(ref mut x: D, ref mut _y: D) {
87         x.1.borrow_mut().push(DropOrder::Function);
88     }
89
90     fn foo_sync(ref mut x: D, ref mut _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(ref mut x: D, _: D) {
96         x.1.borrow_mut().push(DropOrder::Function);
97     }
98
99     fn bar_sync(ref mut 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((ref mut x, _): (D, D)) {
106         x.1.borrow_mut().push(DropOrder::Function);
107     }
108
109     fn baz_sync((ref mut 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(
116         ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
117     ) {
118         x.1.borrow_mut().push(DropOrder::Function);
119     }
120
121     fn foobar_sync(
122         ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
123     ) {
124         x.1.borrow_mut().push(DropOrder::Function);
125     }
126 }
127
128 struct Bar<'a>(PhantomData<&'a ()>);
129
130 impl<'a> Bar<'a> {
131     /// Check that unused bindings are dropped after the method with self is polled.
132     async fn foo_async(&'a self, ref mut x: D, ref mut _y: D) {
133         x.1.borrow_mut().push(DropOrder::Function);
134     }
135
136     fn foo_sync(&'a self, ref mut x: D, ref mut _y: D) {
137         x.1.borrow_mut().push(DropOrder::Function);
138     }
139
140     /// Check that underscore patterns are dropped after the method with self is polled.
141     async fn bar_async(&'a self, ref mut x: D, _: D) {
142         x.1.borrow_mut().push(DropOrder::Function);
143     }
144
145     fn bar_sync(&'a self, ref mut x: D, _: D) {
146         x.1.borrow_mut().push(DropOrder::Function);
147     }
148
149     /// Check that underscore patterns within more complex patterns are dropped after the method
150     /// with self is polled.
151     async fn baz_async(&'a self, (ref mut x, _): (D, D)) {
152         x.1.borrow_mut().push(DropOrder::Function);
153     }
154
155     fn baz_sync(&'a self, (ref mut x, _): (D, D)) {
156         x.1.borrow_mut().push(DropOrder::Function);
157     }
158
159     /// Check that underscore and unused bindings within and outwith more complex patterns are
160     /// dropped after the method with self is polled.
161     async fn foobar_async(
162         &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
163     ) {
164         x.1.borrow_mut().push(DropOrder::Function);
165     }
166
167     fn foobar_sync(
168         &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D,
169     ) {
170         x.1.borrow_mut().push(DropOrder::Function);
171     }
172 }
173
174 fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
175     f: impl FnOnce(DropOrderListPtr) -> Fut,
176     g: impl FnOnce(DropOrderListPtr),
177 ) {
178     let empty = Arc::new(EmptyWaker);
179     let waker = ArcWake::into_waker(empty);
180     let mut cx = Context::from_waker(&waker);
181
182     let actual_order = Rc::new(RefCell::new(Vec::new()));
183     let mut fut = Box::pin(f(actual_order.clone()));
184     let _ = fut.as_mut().poll(&mut cx);
185
186     let expected_order = Rc::new(RefCell::new(Vec::new()));
187     g(expected_order.clone());
188
189     assert_eq!(*actual_order.borrow(), *expected_order.borrow());
190 }
191
192 fn main() {
193     // Free functions (see doc comment on function for what it tests).
194     assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
195                                  |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
196     assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())),
197                                  |l| bar_sync(D("x", l.clone()), D("_", l.clone())));
198     assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))),
199                                  |l| baz_sync((D("x", l.clone()), D("_", l.clone()))));
200     assert_drop_order_after_poll(
201         |l| {
202             foobar_async(
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         |l| {
210             foobar_sync(
211                 D("x", l.clone()),
212                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
213                 D("_", l.clone()),
214                 D("_y", l.clone()),
215             )
216         },
217     );
218
219     // Methods w/out self (see doc comment on function for what it tests).
220     assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
221                                  |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())));
222     assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
223                                  |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())));
224     assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
225                                  |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))));
226     assert_drop_order_after_poll(
227         |l| {
228             Foo::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             Foo::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 (see doc comment on function for what it tests).
246     let b = Bar(Default::default());
247     assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
248                                  |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())));
249     assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
250                                  |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())));
251     assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
252                                  |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))));
253     assert_drop_order_after_poll(
254         |l| {
255             b.foobar_async(
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         |l| {
263             b.foobar_sync(
264                 D("x", l.clone()),
265                 (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
266                 D("_", l.clone()),
267                 D("_y", l.clone()),
268             )
269         },
270     );
271 }