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