Skip to content

Commit 57ec63c

Browse files
committedMay 5, 2019
Add tests for by-ref binding
1 parent 121caa9 commit 57ec63c

3 files changed

+289
-1
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
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+
}

‎src/test/ui/async-await/drop-order-locals-are-hidden.rs

+5
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,9 @@ async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) {
88
assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425]
99
}
1010

11+
async fn baz_async(ref mut x: u32, ref y: u32) {
12+
assert_eq!(__arg0, 1); //~ ERROR cannot find value `__arg0` in this scope [E0425]
13+
assert_eq!(__arg1, 2); //~ ERROR cannot find value `__arg1` in this scope [E0425]
14+
}
15+
1116
fn main() {}

‎src/test/ui/async-await/drop-order-locals-are-hidden.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ error[E0425]: cannot find value `__arg2` in this scope
1010
LL | assert_eq!(__arg2, 4);
1111
| ^^^^^^ not found in this scope
1212

13-
error: aborting due to 2 previous errors
13+
error[E0425]: cannot find value `__arg0` in this scope
14+
--> $DIR/drop-order-locals-are-hidden.rs:12:16
15+
|
16+
LL | assert_eq!(__arg0, 1);
17+
| ^^^^^^ not found in this scope
18+
19+
error[E0425]: cannot find value `__arg1` in this scope
20+
--> $DIR/drop-order-locals-are-hidden.rs:13:16
21+
|
22+
LL | assert_eq!(__arg1, 2);
23+
| ^^^^^^ not found in this scope
24+
25+
error: aborting due to 4 previous errors
1426

1527
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)