175 lines
4.2 KiB
Rust
175 lines
4.2 KiB
Rust
|
// aux-build:arc_wake.rs
|
||
|
// edition:2018
|
||
|
// run-pass
|
||
|
|
||
|
#![deny(dead_code)]
|
||
|
|
||
|
// 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::marker::PhantomData;
|
||
|
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(mut 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,
|
||
|
);
|
||
|
}
|