]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | // aux-build:arc_wake.rs |
2 | // edition:2018 | |
3 | // run-pass | |
4 | ||
416331ca | 5 | #![deny(dead_code)] |
e1599b0c XL |
6 | #![allow(unused_variables)] |
7 | #![allow(unused_must_use)] | |
8 | #![allow(path_statements)] | |
416331ca XL |
9 | |
10 | // Test that the drop order for locals in a fn and async fn matches up. | |
11 | extern crate arc_wake; | |
12 | ||
13 | use arc_wake::ArcWake; | |
14 | use std::cell::RefCell; | |
15 | use std::future::Future; | |
416331ca XL |
16 | use std::pin::Pin; |
17 | use std::rc::Rc; | |
18 | use std::sync::Arc; | |
19 | use std::task::{Context, Poll}; | |
20 | ||
21 | struct EmptyWaker; | |
22 | ||
23 | impl ArcWake for EmptyWaker { | |
24 | fn wake(self: Arc<Self>) {} | |
25 | } | |
26 | ||
27 | #[derive(Debug, Eq, PartialEq)] | |
28 | enum DropOrder { | |
29 | Function, | |
30 | Val(&'static str), | |
31 | } | |
32 | ||
33 | type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>; | |
34 | ||
35 | struct D(&'static str, DropOrderListPtr); | |
36 | ||
37 | impl Drop for D { | |
38 | fn drop(&mut self) { | |
39 | self.1.borrow_mut().push(DropOrder::Val(self.0)); | |
40 | } | |
41 | } | |
42 | ||
43 | struct NeverReady; | |
44 | ||
45 | impl Future for NeverReady { | |
46 | type Output = (); | |
e1599b0c | 47 | fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { |
416331ca XL |
48 | Poll::Pending |
49 | } | |
50 | } | |
51 | ||
52 | async fn simple_variable_declaration_async(l: DropOrderListPtr) { | |
53 | l.borrow_mut().push(DropOrder::Function); | |
54 | let x = D("x", l.clone()); | |
55 | let y = D("y", l.clone()); | |
56 | NeverReady.await; | |
57 | } | |
58 | ||
59 | fn simple_variable_declaration_sync(l: DropOrderListPtr) { | |
60 | l.borrow_mut().push(DropOrder::Function); | |
61 | let x = D("x", l.clone()); | |
62 | let y = D("y", l.clone()); | |
63 | } | |
64 | ||
65 | async fn varable_completely_contained_within_block_async(l: DropOrderListPtr) { | |
66 | l.borrow_mut().push(DropOrder::Function); | |
67 | async { | |
68 | let x = D("x", l.clone()); | |
69 | } | |
70 | .await; | |
71 | let y = D("y", l.clone()); | |
72 | NeverReady.await; | |
73 | } | |
74 | ||
75 | fn varable_completely_contained_within_block_sync(l: DropOrderListPtr) { | |
76 | l.borrow_mut().push(DropOrder::Function); | |
77 | { | |
78 | let x = D("x", l.clone()); | |
79 | } | |
80 | let y = D("y", l.clone()); | |
81 | } | |
82 | ||
83 | async fn variables_moved_into_separate_blocks_async(l: DropOrderListPtr) { | |
84 | l.borrow_mut().push(DropOrder::Function); | |
85 | let x = D("x", l.clone()); | |
86 | let y = D("y", l.clone()); | |
87 | async move { x }.await; | |
88 | async move { y }.await; | |
89 | NeverReady.await; | |
90 | } | |
91 | ||
92 | fn variables_moved_into_separate_blocks_sync(l: DropOrderListPtr) { | |
93 | l.borrow_mut().push(DropOrder::Function); | |
94 | let x = D("x", l.clone()); | |
95 | let y = D("y", l.clone()); | |
96 | { | |
97 | x | |
98 | }; | |
99 | { | |
100 | y | |
101 | }; | |
102 | } | |
103 | ||
104 | async fn variables_moved_into_same_block_async(l: DropOrderListPtr) { | |
105 | l.borrow_mut().push(DropOrder::Function); | |
106 | let x = D("x", l.clone()); | |
107 | let y = D("y", l.clone()); | |
108 | async move { | |
109 | x; | |
110 | y; | |
111 | }; | |
112 | NeverReady.await; | |
113 | } | |
114 | ||
115 | fn variables_moved_into_same_block_sync(l: DropOrderListPtr) { | |
116 | l.borrow_mut().push(DropOrder::Function); | |
117 | let x = D("x", l.clone()); | |
118 | let y = D("y", l.clone()); | |
119 | { | |
120 | x; | |
121 | y; | |
122 | }; | |
123 | return; | |
124 | } | |
125 | ||
126 | async fn move_after_current_await_doesnt_affect_order(l: DropOrderListPtr) { | |
127 | l.borrow_mut().push(DropOrder::Function); | |
128 | let x = D("x", l.clone()); | |
129 | let y = D("y", l.clone()); | |
130 | NeverReady.await; | |
131 | async move { | |
132 | x; | |
133 | y; | |
134 | }; | |
135 | } | |
136 | ||
137 | fn assert_drop_order_after_cancel<Fut: Future<Output = ()>>( | |
138 | f: impl FnOnce(DropOrderListPtr) -> Fut, | |
139 | g: impl FnOnce(DropOrderListPtr), | |
140 | ) { | |
141 | let empty = Arc::new(EmptyWaker); | |
142 | let waker = ArcWake::into_waker(empty); | |
143 | let mut cx = Context::from_waker(&waker); | |
144 | ||
145 | let actual_order = Rc::new(RefCell::new(Vec::new())); | |
146 | let mut fut = Box::pin(f(actual_order.clone())); | |
147 | let _ = fut.as_mut().poll(&mut cx); | |
148 | drop(fut); | |
149 | ||
150 | let expected_order = Rc::new(RefCell::new(Vec::new())); | |
151 | g(expected_order.clone()); | |
152 | assert_eq!(*actual_order.borrow(), *expected_order.borrow()); | |
153 | } | |
154 | ||
155 | fn main() { | |
156 | assert_drop_order_after_cancel( | |
157 | simple_variable_declaration_async, | |
158 | simple_variable_declaration_sync, | |
159 | ); | |
160 | assert_drop_order_after_cancel( | |
161 | varable_completely_contained_within_block_async, | |
162 | varable_completely_contained_within_block_sync, | |
163 | ); | |
164 | assert_drop_order_after_cancel( | |
165 | variables_moved_into_separate_blocks_async, | |
166 | variables_moved_into_separate_blocks_sync, | |
167 | ); | |
168 | assert_drop_order_after_cancel( | |
169 | variables_moved_into_same_block_async, | |
170 | variables_moved_into_same_block_sync, | |
171 | ); | |
172 | assert_drop_order_after_cancel( | |
173 | move_after_current_await_doesnt_affect_order, | |
174 | simple_variable_declaration_sync, | |
175 | ); | |
176 | } |