1 // aux-build:arc_wake.rs
5 // revisions: default nomiropt
6 //[nomiropt]compile-flags: -Z mir-opt-level=0
8 #![allow(unused_variables)]
10 // Test the drop order for parameters relative to local variables and
11 // temporaries created in the tail return expression of the function
12 // body. In particular, check that this drop order is the same between
13 // an `async fn` and an ordinary `fn`. See #64512.
15 extern crate arc_wake;
17 use arc_wake::ArcWake;
18 use std::cell::RefCell;
19 use std::future::Future;
22 use std::task::Context;
26 impl ArcWake for EmptyWaker {
27 fn wake(self: Arc<Self>) {}
30 #[derive(Debug, Eq, PartialEq)]
36 type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
38 struct D(&'static str, DropOrderListPtr);
42 self.1.borrow_mut().push(DropOrder::Val(self.0));
46 /// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
53 async fn foo_async(x: D, _y: D) {
55 let z = D("z", l.clone());
56 l.borrow_mut().push(DropOrder::Function);
57 helper_async(&D("temp", l)).await
60 async fn helper_async(v: &D) { }
62 fn foo_sync(x: D, _y: D) {
64 let z = D("z", l.clone());
65 l.borrow_mut().push(DropOrder::Function);
66 helper_sync(&D("temp", l))
69 fn helper_sync(v: &D) { }
71 fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
72 f: impl FnOnce(DropOrderListPtr) -> Fut,
73 g: impl FnOnce(DropOrderListPtr),
75 let empty = Arc::new(EmptyWaker);
76 let waker = ArcWake::into_waker(empty);
77 let mut cx = Context::from_waker(&waker);
79 let actual_order = Rc::new(RefCell::new(Vec::new()));
80 let mut fut = Box::pin(f(actual_order.clone()));
81 let r = fut.as_mut().poll(&mut cx);
84 std::task::Poll::Ready(()) => true,
88 let expected_order = Rc::new(RefCell::new(Vec::new()));
89 g(expected_order.clone());
91 assert_eq!(*actual_order.borrow(), *expected_order.borrow());
95 // Free functions (see doc comment on function for what it tests).
96 assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
97 |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));