Skip to content

Commit f8150f4

Browse files
committed
Enforce consistent drop order w/ async methods.
This commit extends the previous commit to apply to trait methods as well as free functions.
1 parent f566e98 commit f8150f4

File tree

2 files changed

+130
-9
lines changed

2 files changed

+130
-9
lines changed

src/librustc/hir/lowering.rs

+27-9
Original file line numberDiff line numberDiff line change
@@ -3413,15 +3413,33 @@ impl<'a> LoweringContext<'a> {
34133413
)
34143414
}
34153415
ImplItemKind::Method(ref sig, ref body) => {
3416-
let body_id = self.lower_async_body(&sig.decl, &sig.header.asyncness.node, body);
3417-
let impl_trait_return_allow = !self.is_in_trait_impl;
3418-
let (generics, sig) = self.lower_method_sig(
3419-
&i.generics,
3420-
sig,
3421-
impl_item_def_id,
3422-
impl_trait_return_allow,
3423-
sig.header.asyncness.node.opt_return_id(),
3424-
);
3416+
let mut lower_method = |sig: &MethodSig| {
3417+
let body_id = self.lower_async_body(
3418+
&sig.decl, &sig.header.asyncness.node, body
3419+
);
3420+
let impl_trait_return_allow = !self.is_in_trait_impl;
3421+
let (generics, sig) = self.lower_method_sig(
3422+
&i.generics,
3423+
sig,
3424+
impl_item_def_id,
3425+
impl_trait_return_allow,
3426+
sig.header.asyncness.node.opt_return_id(),
3427+
);
3428+
(body_id, generics, sig)
3429+
};
3430+
3431+
let (body_id, generics, sig) = if let IsAsync::Async {
3432+
ref arguments, ..
3433+
} = sig.header.asyncness.node {
3434+
let mut sig = sig.clone();
3435+
// Replace the arguments of this async function with the generated
3436+
// arguments that will be moved into the closure.
3437+
sig.decl.inputs = arguments.clone().drain(..).map(|a| a.arg).collect();
3438+
lower_method(&sig)
3439+
} else {
3440+
lower_method(sig)
3441+
};
3442+
34253443
(generics, hir::ImplItemKind::Method(sig, body_id))
34263444
}
34273445
ImplItemKind::Type(ref ty) => (

src/test/run-pass/issue-54716.rs

+103
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extern crate arc_wake;
1010
use arc_wake::ArcWake;
1111
use std::cell::RefCell;
1212
use std::future::Future;
13+
use std::marker::PhantomData;
1314
use std::sync::Arc;
1415

1516
struct EmptyWaker;
@@ -48,6 +49,46 @@ async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
4849
x.1.borrow_mut().push(DropOrder::Function);
4950
}
5051

52+
struct Foo;
53+
54+
impl Foo {
55+
async fn foo(x: D, _y: D) {
56+
x.1.borrow_mut().push(DropOrder::Function);
57+
}
58+
59+
async fn bar(x: D, _: D) {
60+
x.1.borrow_mut().push(DropOrder::Function);
61+
}
62+
63+
async fn baz((x, _): (D, D)) {
64+
x.1.borrow_mut().push(DropOrder::Function);
65+
}
66+
67+
async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
68+
x.1.borrow_mut().push(DropOrder::Function);
69+
}
70+
}
71+
72+
struct Bar<'a>(PhantomData<&'a ()>);
73+
74+
impl<'a> Bar<'a> {
75+
async fn foo(&'a self, x: D, _y: D) {
76+
x.1.borrow_mut().push(DropOrder::Function);
77+
}
78+
79+
async fn bar(&'a self, x: D, _: D) {
80+
x.1.borrow_mut().push(DropOrder::Function);
81+
}
82+
83+
async fn baz(&'a self, (x, _): (D, D)) {
84+
x.1.borrow_mut().push(DropOrder::Function);
85+
}
86+
87+
async fn foobar(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
88+
x.1.borrow_mut().push(DropOrder::Function);
89+
}
90+
}
91+
5192
fn main() {
5293
let empty = Arc::new(EmptyWaker);
5394
let waker = ArcWake::into_waker(empty);
@@ -58,6 +99,8 @@ fn main() {
5899
// non-async functions. This is because the drop order of captured variables doesn't match the
59100
// drop order of arguments in a function.
60101

102+
// Free functions
103+
61104
let af = Arc::new(RefCell::new(Vec::new()));
62105
let mut fut = Box::pin(foo(D("x", af.clone()), D("_y", af.clone())));
63106
let _ = fut.as_mut().poll(&waker);
@@ -84,4 +127,64 @@ fn main() {
84127
assert_eq!(*af.borrow(), &[
85128
Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_"),
86129
]);
130+
131+
// Methods w/out self
132+
133+
let af = Arc::new(RefCell::new(Vec::new()));
134+
let mut fut = Box::pin(Foo::foo(D("x", af.clone()), D("_y", af.clone())));
135+
let _ = fut.as_mut().poll(&waker);
136+
assert_eq!(*af.borrow(), &[Function, Val("_y"), Val("x")]);
137+
138+
let af = Arc::new(RefCell::new(Vec::new()));
139+
let mut fut = Box::pin(Foo::bar(D("x", af.clone()), D("_", af.clone())));
140+
let _ = fut.as_mut().poll(&waker);
141+
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
142+
143+
let af = Arc::new(RefCell::new(Vec::new()));
144+
let mut fut = Box::pin(Foo::baz((D("x", af.clone()), D("_", af.clone()))));
145+
let _ = fut.as_mut().poll(&waker);
146+
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
147+
148+
let af = Arc::new(RefCell::new(Vec::new()));
149+
let mut fut = Box::pin(Foo::foobar(
150+
D("x", af.clone()),
151+
(D("a", af.clone()), D("_", af.clone()), D("_c", af.clone())),
152+
D("_", af.clone()),
153+
D("_y", af.clone()),
154+
));
155+
let _ = fut.as_mut().poll(&waker);
156+
assert_eq!(*af.borrow(), &[
157+
Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_"),
158+
]);
159+
160+
// Methods
161+
162+
let b = Bar(Default::default());
163+
164+
let af = Arc::new(RefCell::new(Vec::new()));
165+
let mut fut = Box::pin(b.foo(D("x", af.clone()), D("_y", af.clone())));
166+
let _ = fut.as_mut().poll(&waker);
167+
assert_eq!(*af.borrow(), &[Function, Val("_y"), Val("x")]);
168+
169+
let af = Arc::new(RefCell::new(Vec::new()));
170+
let mut fut = Box::pin(b.bar(D("x", af.clone()), D("_", af.clone())));
171+
let _ = fut.as_mut().poll(&waker);
172+
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
173+
174+
let af = Arc::new(RefCell::new(Vec::new()));
175+
let mut fut = Box::pin(b.baz((D("x", af.clone()), D("_", af.clone()))));
176+
let _ = fut.as_mut().poll(&waker);
177+
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
178+
179+
let af = Arc::new(RefCell::new(Vec::new()));
180+
let mut fut = Box::pin(b.foobar(
181+
D("x", af.clone()),
182+
(D("a", af.clone()), D("_", af.clone()), D("_c", af.clone())),
183+
D("_", af.clone()),
184+
D("_y", af.clone()),
185+
));
186+
let _ = fut.as_mut().poll(&waker);
187+
assert_eq!(*af.borrow(), &[
188+
Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_"),
189+
]);
87190
}

0 commit comments

Comments
 (0)