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