about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/run-pass/issue-54716.rs184
-rw-r--r--src/test/ui/async-await/auxiliary/arc_wake.rs64
-rw-r--r--src/test/ui/async-await/drop-order-for-async-fn-parameters.rs263
-rw-r--r--src/test/ui/async-await/drop-order-locals-are-hidden.rs11
-rw-r--r--src/test/ui/async-await/drop-order-locals-are-hidden.stderr15
5 files changed, 353 insertions, 184 deletions
diff --git a/src/test/run-pass/issue-54716.rs b/src/test/run-pass/issue-54716.rs
deleted file mode 100644
index 961c412f5ec..00000000000
--- a/src/test/run-pass/issue-54716.rs
+++ /dev/null
@@ -1,184 +0,0 @@
-// aux-build:arc_wake.rs
-// edition:2018
-// run-pass
-
-#![allow(unused_variables)]
-#![feature(async_await, await_macro)]
-
-extern crate arc_wake;
-
-use arc_wake::ArcWake;
-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;
-
-impl ArcWake for EmptyWaker {
-    fn wake(self: Arc<Self>) {}
-}
-
-#[derive(Debug, Eq, PartialEq)]
-enum DropOrder {
-    Function,
-    Val(&'static str),
-}
-
-type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
-
-struct D(&'static str, DropOrderListPtr);
-
-impl Drop for D {
-    fn drop(&mut self) {
-        self.1.borrow_mut().push(DropOrder::Val(self.0));
-    }
-}
-
-/// 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);
-}
-
-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);
-    }
-}
-
-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 assert_drop_order_after_poll<Fut: Future<Output = ()>>(
-    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);
-
-    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!(*actual_order.borrow(), expected_order);
-}
-
-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());
-    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("_")]);
-}
diff --git a/src/test/ui/async-await/auxiliary/arc_wake.rs b/src/test/ui/async-await/auxiliary/arc_wake.rs
new file mode 100644
index 00000000000..c21886f26f4
--- /dev/null
+++ b/src/test/ui/async-await/auxiliary/arc_wake.rs
@@ -0,0 +1,64 @@
+// edition:2018
+
+use std::sync::Arc;
+use std::task::{
+    Waker, RawWaker, RawWakerVTable,
+};
+
+macro_rules! waker_vtable {
+    ($ty:ident) => {
+        &RawWakerVTable::new(
+            clone_arc_raw::<$ty>,
+            wake_arc_raw::<$ty>,
+            wake_by_ref_arc_raw::<$ty>,
+            drop_arc_raw::<$ty>,
+        )
+    };
+}
+
+pub trait ArcWake {
+    fn wake(self: Arc<Self>);
+
+    fn wake_by_ref(arc_self: &Arc<Self>) {
+        arc_self.clone().wake()
+    }
+
+    fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
+    {
+        let ptr = Arc::into_raw(wake) as *const ();
+
+        unsafe {
+            Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
+        }
+    }
+}
+
+unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
+    // Retain Arc by creating a copy
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    let arc_clone = arc.clone();
+    // Forget the Arcs again, so that the refcount isn't decrased
+    let _ = Arc::into_raw(arc);
+    let _ = Arc::into_raw(arc_clone);
+}
+
+unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
+    increase_refcount::<T>(data);
+    RawWaker::new(data, waker_vtable!(T))
+}
+
+unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
+    // Drop Arc
+    let _: Arc<T> = Arc::from_raw(data as *const T);
+}
+
+unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    ArcWake::wake(arc);
+}
+
+unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    ArcWake::wake_by_ref(&arc);
+    let _ = Arc::into_raw(arc);
+}
diff --git a/src/test/ui/async-await/drop-order-for-async-fn-parameters.rs b/src/test/ui/async-await/drop-order-for-async-fn-parameters.rs
new file mode 100644
index 00000000000..708c5704984
--- /dev/null
+++ b/src/test/ui/async-await/drop-order-for-async-fn-parameters.rs
@@ -0,0 +1,263 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+#![feature(async_await, await_macro)]
+
+// Test that the drop order for parameters in a fn and async fn matches up. Also test that
+// parameters (used or unused) are not dropped until the async fn completes execution.
+// See also #54716.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+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;
+
+impl ArcWake for EmptyWaker {
+    fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+    Function,
+    Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+    fn drop(&mut self) {
+        self.1.borrow_mut().push(DropOrder::Val(self.0));
+    }
+}
+
+/// Check that unused bindings are dropped after the function is polled.
+async fn foo_async(x: D, _y: D) {
+    x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn foo_sync(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_async(x: D, _: D) {
+    x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn bar_sync(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_async((x, _): (D, D)) {
+    x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn baz_sync((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_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+    x.1.borrow_mut().push(DropOrder::Function);
+}
+
+fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+    x.1.borrow_mut().push(DropOrder::Function);
+}
+
+struct Foo;
+
+impl Foo {
+    /// Check that unused bindings are dropped after the method is polled.
+    async fn foo_async(x: D, _y: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn foo_sync(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_async(x: D, _: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn bar_sync(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_async((x, _): (D, D)) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn baz_sync((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_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn foobar_sync(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> {
+    /// Check that unused bindings are dropped after the method with self is polled.
+    async fn foo_async(&'a self, x: D, _y: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn foo_sync(&'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_async(&'a self, x: D, _: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn bar_sync(&'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_async(&'a self, (x, _): (D, D)) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn baz_sync(&'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_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+
+    fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
+        x.1.borrow_mut().push(DropOrder::Function);
+    }
+}
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+    f: impl FnOnce(DropOrderListPtr) -> Fut,
+    g: impl FnOnce(DropOrderListPtr),
+) {
+    let empty = Arc::new(EmptyWaker);
+    let waker = ArcWake::into_waker(empty);
+    let mut cx = Context::from_waker(&waker);
+
+    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);
+
+    let expected_order = Rc::new(RefCell::new(Vec::new()));
+    g(expected_order.clone());
+
+    assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+    // Free functions (see doc comment on function for what it tests).
+    assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+                                 |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+    assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())),
+                                 |l| bar_sync(D("x", l.clone()), D("_", l.clone())));
+    assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))),
+                                 |l| baz_sync((D("x", l.clone()), D("_", l.clone()))));
+    assert_drop_order_after_poll(
+        |l| {
+            foobar_async(
+                D("x", l.clone()),
+                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+                D("_", l.clone()),
+                D("_y", l.clone()),
+            )
+        },
+        |l| {
+            foobar_sync(
+                D("x", l.clone()),
+                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+                D("_", l.clone()),
+                D("_y", l.clone()),
+            )
+        },
+    );
+
+    // Methods w/out self (see doc comment on function for what it tests).
+    assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())),
+                                 |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())));
+    assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())),
+                                 |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())));
+    assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))),
+                                 |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))));
+    assert_drop_order_after_poll(
+        |l| {
+            Foo::foobar_async(
+                D("x", l.clone()),
+                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+                D("_", l.clone()),
+                D("_y", l.clone()),
+            )
+        },
+        |l| {
+            Foo::foobar_sync(
+                D("x", l.clone()),
+                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+                D("_", l.clone()),
+                D("_y", l.clone()),
+            )
+        },
+    );
+
+    // Methods (see doc comment on function for what it tests).
+    let b = Bar(Default::default());
+    assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())),
+                                 |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())));
+    assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())),
+                                 |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())));
+    assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))),
+                                 |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))));
+    assert_drop_order_after_poll(
+        |l| {
+            b.foobar_async(
+                D("x", l.clone()),
+                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+                D("_", l.clone()),
+                D("_y", l.clone()),
+            )
+        },
+        |l| {
+            b.foobar_sync(
+                D("x", l.clone()),
+                (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
+                D("_", l.clone()),
+                D("_y", l.clone()),
+            )
+        },
+    );
+}
diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.rs b/src/test/ui/async-await/drop-order-locals-are-hidden.rs
new file mode 100644
index 00000000000..10dc5e27f6f
--- /dev/null
+++ b/src/test/ui/async-await/drop-order-locals-are-hidden.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+#![allow(unused_variables)]
+#![feature(async_await)]
+
+async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) {
+    assert_eq!(__arg1, (1, 2, 3)); //~ ERROR cannot find value `__arg1` in this scope [E0425]
+    assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425]
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/drop-order-locals-are-hidden.stderr b/src/test/ui/async-await/drop-order-locals-are-hidden.stderr
new file mode 100644
index 00000000000..ca0da6b7c96
--- /dev/null
+++ b/src/test/ui/async-await/drop-order-locals-are-hidden.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find value `__arg1` in this scope
+  --> $DIR/drop-order-locals-are-hidden.rs:7:16
+   |
+LL |     assert_eq!(__arg1, (1, 2, 3));
+   |                ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `__arg2` in this scope
+  --> $DIR/drop-order-locals-are-hidden.rs:8:16
+   |
+LL |     assert_eq!(__arg2, 4);
+   |                ^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.