// aux-build:arc_wake.rs
// edition:2018
// run-pass

#![deny(dead_code)]
#![allow(unused_variables)]
#![allow(unused_must_use)]
#![allow(path_statements)]

// 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::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(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,
    );
}
