Skip to content

Commit c4940e0

Browse files
committed
test drop order for locals when a future is dropped part-way through execution
1 parent 3882ed4 commit c4940e0

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// aux-build:arc_wake.rs
2+
// edition:2018
3+
// run-pass
4+
5+
#![allow(unused_variables)]
6+
#![deny(dead_code)]
7+
#![feature(async_await)]
8+
9+
// Test that the drop order for locals in a fn and async fn matches up.
10+
extern crate arc_wake;
11+
12+
use arc_wake::ArcWake;
13+
use std::cell::RefCell;
14+
use std::future::Future;
15+
use std::marker::PhantomData;
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 = ();
47+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
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+
}

0 commit comments

Comments
 (0)