Skip to content

Commit f40190a

Browse files
committed
test drop order for parameters when a future is dropped part-way through execution
1 parent 0a1bdd4 commit f40190a

File tree

1 file changed

+307
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)