]> git.lizzy.rs Git - rust.git/blob - tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
Rollup merge of #107061 - compiler-errors:new-solver-new-candidates-3, r=lcnr
[rust.git] / tests / ui / async-await / drop-order / drop-order-for-temporary-in-tail-return-expr.rs
1 // aux-build:arc_wake.rs
2 // edition:2018
3 // run-pass
4
5 // revisions: default nomiropt
6 //[nomiropt]compile-flags: -Z mir-opt-level=0
7
8 #![allow(unused_variables)]
9
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.
14
15 extern crate arc_wake;
16
17 use arc_wake::ArcWake;
18 use std::cell::RefCell;
19 use std::future::Future;
20 use std::sync::Arc;
21 use std::rc::Rc;
22 use std::task::Context;
23
24 struct EmptyWaker;
25
26 impl ArcWake for EmptyWaker {
27     fn wake(self: Arc<Self>) {}
28 }
29
30 #[derive(Debug, Eq, PartialEq)]
31 enum DropOrder {
32     Function,
33     Val(&'static str),
34 }
35
36 type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
37
38 struct D(&'static str, DropOrderListPtr);
39
40 impl Drop for D {
41     fn drop(&mut self) {
42         self.1.borrow_mut().push(DropOrder::Val(self.0));
43     }
44 }
45
46 /// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
47 ///
48 /// Expected order:
49 /// - `z`
50 /// - temp
51 /// - `y`
52 /// - `x`
53 async fn foo_async(x: D, _y: D) {
54     let l = x.1.clone();
55     let z = D("z", l.clone());
56     l.borrow_mut().push(DropOrder::Function);
57     helper_async(&D("temp", l)).await
58 }
59
60 async fn helper_async(v: &D) { }
61
62 fn foo_sync(x: D, _y: D) {
63     let l = x.1.clone();
64     let z = D("z", l.clone());
65     l.borrow_mut().push(DropOrder::Function);
66     helper_sync(&D("temp", l))
67 }
68
69 fn helper_sync(v: &D) { }
70
71 fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
72     f: impl FnOnce(DropOrderListPtr) -> Fut,
73     g: impl FnOnce(DropOrderListPtr),
74 ) {
75     let empty = Arc::new(EmptyWaker);
76     let waker = ArcWake::into_waker(empty);
77     let mut cx = Context::from_waker(&waker);
78
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);
82
83     assert!(match r {
84         std::task::Poll::Ready(()) => true,
85         _ => false,
86     });
87
88     let expected_order = Rc::new(RefCell::new(Vec::new()));
89     g(expected_order.clone());
90
91     assert_eq!(*actual_order.borrow(), *expected_order.borrow());
92 }
93
94 fn main() {
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())));
98 }