Skip to content

Commit 6134655

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 7c6dc7a commit 6134655

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
@@ -3611,15 +3611,33 @@ impl<'a> LoweringContext<'a> {
36113611
)
36123612
}
36133613
ImplItemKind::Method(ref sig, ref body) => {
3614-
let body_id = self.lower_async_body(&sig.decl, &sig.header.asyncness.node, body);
3615-
let impl_trait_return_allow = !self.is_in_trait_impl;
3616-
let (generics, sig) = self.lower_method_sig(
3617-
&i.generics,
3618-
sig,
3619-
impl_item_def_id,
3620-
impl_trait_return_allow,
3621-
sig.header.asyncness.node.opt_return_id(),
3622-
);
3614+
let mut lower_method = |sig: &MethodSig| {
3615+
let body_id = self.lower_async_body(
3616+
&sig.decl, &sig.header.asyncness.node, body
3617+
);
3618+
let impl_trait_return_allow = !self.is_in_trait_impl;
3619+
let (generics, sig) = self.lower_method_sig(
3620+
&i.generics,
3621+
sig,
3622+
impl_item_def_id,
3623+
impl_trait_return_allow,
3624+
sig.header.asyncness.node.opt_return_id(),
3625+
);
3626+
(body_id, generics, sig)
3627+
};
3628+
3629+
let (body_id, generics, sig) = if let IsAsync::Async {
3630+
ref arguments, ..
3631+
} = sig.header.asyncness.node {
3632+
let mut sig = sig.clone();
3633+
// Replace the arguments of this async function with the generated
3634+
// arguments that will be moved into the closure.
3635+
sig.decl.inputs = arguments.clone().drain(..).map(|a| a.arg).collect();
3636+
lower_method(&sig)
3637+
} else {
3638+
lower_method(sig)
3639+
};
3640+
36233641
(generics, hir::ImplItemKind::Method(sig, body_id))
36243642
}
36253643
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
use std::task::Context;
1516

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

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

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

0 commit comments

Comments
 (0)