diff --git a/src/test/run-pass/issue-54716.rs b/src/test/run-pass/issue-54716.rs index d075d2d619106..ea4f5e076b005 100644 --- a/src/test/run-pass/issue-54716.rs +++ b/src/test/run-pass/issue-54716.rs @@ -12,6 +12,7 @@ use std::cell::RefCell; use std::future::Future; use std::marker::PhantomData; use std::sync::Arc; +use std::rc::Rc; use std::task::Context; struct EmptyWaker; @@ -26,7 +27,9 @@ enum DropOrder { Val(&'static str), } -struct D(&'static str, Arc>>); +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); impl Drop for D { fn drop(&mut self) { @@ -34,18 +37,24 @@ impl Drop for D { } } +/// Check that unused bindings are dropped after the function is polled. async fn foo(x: D, _y: D) { x.1.borrow_mut().push(DropOrder::Function); } +/// Check that underscore patterns are dropped after the function is polled. async fn bar(x: D, _: D) { x.1.borrow_mut().push(DropOrder::Function); } +/// Check that underscore patterns within more complex patterns are dropped after the function +/// is polled. async fn baz((x, _): (D, D)) { x.1.borrow_mut().push(DropOrder::Function); } +/// Check that underscore and unused bindings within and outwith more complex patterns are dropped +/// after the function is polled. async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { x.1.borrow_mut().push(DropOrder::Function); } @@ -53,18 +62,24 @@ async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { struct Foo; impl Foo { + /// Check that unused bindings are dropped after the method is polled. async fn foo(x: D, _y: D) { x.1.borrow_mut().push(DropOrder::Function); } + /// Check that underscore patterns are dropped after the method is polled. async fn bar(x: D, _: D) { x.1.borrow_mut().push(DropOrder::Function); } + /// Check that underscore patterns within more complex patterns are dropped after the method + /// is polled. async fn baz((x, _): (D, D)) { x.1.borrow_mut().push(DropOrder::Function); } + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method is polled. async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { x.1.borrow_mut().push(DropOrder::Function); } @@ -73,120 +88,97 @@ impl Foo { struct Bar<'a>(PhantomData<&'a ()>); impl<'a> Bar<'a> { + /// Check that unused bindings are dropped after the method with self is polled. async fn foo(&'a self, x: D, _y: D) { x.1.borrow_mut().push(DropOrder::Function); } + /// Check that underscore patterns are dropped after the method with self is polled. async fn bar(&'a self, x: D, _: D) { x.1.borrow_mut().push(DropOrder::Function); } + /// Check that underscore patterns within more complex patterns are dropped after the method + /// with self is polled. async fn baz(&'a self, (x, _): (D, D)) { x.1.borrow_mut().push(DropOrder::Function); } + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method with self is polled. async fn foobar(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) { x.1.borrow_mut().push(DropOrder::Function); } } -fn main() { +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + expected_order: &[DropOrder], +) { let empty = Arc::new(EmptyWaker); let waker = ArcWake::into_waker(empty); let mut cx = Context::from_waker(&waker); - use DropOrder::*; - - // Currently, the `bar` and `foobar` tests do not output the same order as the equivalent - // 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); - assert_eq!(*af.borrow(), &[Function, Val("_y"), Val("x")]); - - let af = Arc::new(RefCell::new(Vec::new())); - let mut fut = Box::pin(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(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(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 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 actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.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("_"), - ]); + assert_eq!(*actual_order.borrow(), expected_order); +} - // Methods +fn main() { + use DropOrder::*; + // At time of writing (23/04/19), the `bar` and `foobar` tests do not output the same order as + // the equivalent 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 (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo(D("x", l.clone()), D("_y", l.clone())), + &[Function, Val("_y"), Val("x")]); + assert_drop_order_after_poll(|l| bar(D("x", l.clone()), D("_", l.clone())), + &[Function, Val("x"), Val("_")]); + assert_drop_order_after_poll(|l| baz((D("x", l.clone()), D("_", l.clone()))), + &[Function, Val("x"), Val("_")]); + assert_drop_order_after_poll(|l| { + foobar( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, &[Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_")]); + + // Methods w/out self (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| Foo::foo(D("x", l.clone()), D("_y", l.clone())), + &[Function, Val("_y"), Val("x")]); + assert_drop_order_after_poll(|l| Foo::bar(D("x", l.clone()), D("_", l.clone())), + &[Function, Val("x"), Val("_")]); + assert_drop_order_after_poll(|l| Foo::baz((D("x", l.clone()), D("_", l.clone()))), + &[Function, Val("x"), Val("_")]); + assert_drop_order_after_poll(|l| { + Foo::foobar( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, &[Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_")]); + + // Methods (see doc comment on function for what it tests). 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("_"), - ]); + assert_drop_order_after_poll(|l| b.foo(D("x", l.clone()), D("_y", l.clone())), + &[Function, Val("_y"), Val("x")]); + assert_drop_order_after_poll(|l| b.bar(D("x", l.clone()), D("_", l.clone())), + &[Function, Val("x"), Val("_")]); + assert_drop_order_after_poll(|l| b.baz((D("x", l.clone()), D("_", l.clone()))), + &[Function, Val("x"), Val("_")]); + assert_drop_order_after_poll(|l| { + b.foobar( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, &[Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_")]); }