summaryrefslogtreecommitdiffstats
path: root/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs')
-rw-r--r--tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs176
1 files changed, 176 insertions, 0 deletions
diff --git a/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs b/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
new file mode 100644
index 000000000..15cc9fbc8
--- /dev/null
+++ b/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
@@ -0,0 +1,176 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![deny(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_must_use)]
+#![allow(path_statements)]
+
+// Test that the drop order for locals in a fn and async fn matches up.
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::pin::Pin;
+use std::rc::Rc;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+
+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));
+ }
+}
+
+struct NeverReady;
+
+impl Future for NeverReady {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+async fn simple_variable_declaration_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ NeverReady.await;
+}
+
+fn simple_variable_declaration_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+}
+
+async fn varable_completely_contained_within_block_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ async {
+ let x = D("x", l.clone());
+ }
+ .await;
+ let y = D("y", l.clone());
+ NeverReady.await;
+}
+
+fn varable_completely_contained_within_block_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ {
+ let x = D("x", l.clone());
+ }
+ let y = D("y", l.clone());
+}
+
+async fn variables_moved_into_separate_blocks_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ async move { x }.await;
+ async move { y }.await;
+ NeverReady.await;
+}
+
+fn variables_moved_into_separate_blocks_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ {
+ x
+ };
+ {
+ y
+ };
+}
+
+async fn variables_moved_into_same_block_async(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ async move {
+ x;
+ y;
+ };
+ NeverReady.await;
+}
+
+fn variables_moved_into_same_block_sync(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ {
+ x;
+ y;
+ };
+ return;
+}
+
+async fn move_after_current_await_doesnt_affect_order(l: DropOrderListPtr) {
+ l.borrow_mut().push(DropOrder::Function);
+ let x = D("x", l.clone());
+ let y = D("y", l.clone());
+ NeverReady.await;
+ async move {
+ x;
+ y;
+ };
+}
+
+fn assert_drop_order_after_cancel<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);
+ drop(fut);
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ assert_drop_order_after_cancel(
+ simple_variable_declaration_async,
+ simple_variable_declaration_sync,
+ );
+ assert_drop_order_after_cancel(
+ varable_completely_contained_within_block_async,
+ varable_completely_contained_within_block_sync,
+ );
+ assert_drop_order_after_cancel(
+ variables_moved_into_separate_blocks_async,
+ variables_moved_into_separate_blocks_sync,
+ );
+ assert_drop_order_after_cancel(
+ variables_moved_into_same_block_async,
+ variables_moved_into_same_block_sync,
+ );
+ assert_drop_order_after_cancel(
+ move_after_current_await_doesnt_affect_order,
+ simple_variable_declaration_sync,
+ );
+}