Enforce consistent drop order w/ async methods.
This commit extends the previous commit to apply to trait methods as well as free functions.
This commit is contained in:
parent
7c6dc7a254
commit
61346557ce
@ -3611,15 +3611,33 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
|
||||
)
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
let body_id = self.lower_async_body(&sig.decl, &sig.header.asyncness.node, body);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
sig,
|
||||
impl_item_def_id,
|
||||
impl_trait_return_allow,
|
||||
sig.header.asyncness.node.opt_return_id(),
|
||||
);
|
||||
let mut lower_method = |sig: &MethodSig| {
|
||||
let body_id = self.lower_async_body(
|
||||
&sig.decl, &sig.header.asyncness.node, body
|
||||
);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
sig,
|
||||
impl_item_def_id,
|
||||
impl_trait_return_allow,
|
||||
sig.header.asyncness.node.opt_return_id(),
|
||||
);
|
||||
(body_id, generics, sig)
|
||||
};
|
||||
|
||||
let (body_id, generics, sig) = if let IsAsync::Async {
|
||||
ref arguments, ..
|
||||
} = sig.header.asyncness.node {
|
||||
let mut sig = sig.clone();
|
||||
// Replace the arguments of this async function with the generated
|
||||
// arguments that will be moved into the closure.
|
||||
sig.decl.inputs = arguments.clone().drain(..).map(|a| a.arg).collect();
|
||||
lower_method(&sig)
|
||||
} else {
|
||||
lower_method(sig)
|
||||
};
|
||||
|
||||
(generics, hir::ImplItemKind::Method(sig, body_id))
|
||||
}
|
||||
ImplItemKind::Type(ref ty) => (
|
||||
|
@ -10,6 +10,7 @@
|
||||
use arc_wake::ArcWake;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::task::Context;
|
||||
|
||||
@ -49,6 +50,46 @@ async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
async fn foo(x: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
async fn bar(x: D, _: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
async fn baz((x, _): (D, D)) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
}
|
||||
|
||||
struct Bar<'a>(PhantomData<&'a ()>);
|
||||
|
||||
impl<'a> Bar<'a> {
|
||||
async fn foo(&'a self, x: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
async fn bar(&'a self, x: D, _: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
async fn baz(&'a self, (x, _): (D, D)) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
async fn foobar(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let empty = Arc::new(EmptyWaker);
|
||||
let waker = ArcWake::into_waker(empty);
|
||||
@ -60,6 +101,8 @@ fn main() {
|
||||
// non-async functions. This is because the drop order of captured variables doesn't match the
|
||||
// drop order of arguments in a function.
|
||||
|
||||
// Free functions
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(foo(D("x", af.clone()), D("_y", af.clone())));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
@ -86,4 +129,64 @@ fn main() {
|
||||
assert_eq!(*af.borrow(), &[
|
||||
Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_"),
|
||||
]);
|
||||
|
||||
// Methods w/out self
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(Foo::foo(D("x", af.clone()), D("_y", af.clone())));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[Function, Val("_y"), Val("x")]);
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(Foo::bar(D("x", af.clone()), D("_", af.clone())));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(Foo::baz((D("x", af.clone()), D("_", af.clone()))));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(Foo::foobar(
|
||||
D("x", af.clone()),
|
||||
(D("a", af.clone()), D("_", af.clone()), D("_c", af.clone())),
|
||||
D("_", af.clone()),
|
||||
D("_y", af.clone()),
|
||||
));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[
|
||||
Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_"),
|
||||
]);
|
||||
|
||||
// Methods
|
||||
|
||||
let b = Bar(Default::default());
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(b.foo(D("x", af.clone()), D("_y", af.clone())));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[Function, Val("_y"), Val("x")]);
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(b.bar(D("x", af.clone()), D("_", af.clone())));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(b.baz((D("x", af.clone()), D("_", af.clone()))));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[Function, Val("x"), Val("_")]);
|
||||
|
||||
let af = Arc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(b.foobar(
|
||||
D("x", af.clone()),
|
||||
(D("a", af.clone()), D("_", af.clone()), D("_c", af.clone())),
|
||||
D("_", af.clone()),
|
||||
D("_y", af.clone()),
|
||||
));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
assert_eq!(*af.borrow(), &[
|
||||
Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_"),
|
||||
]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user