// Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync #![feature(async_trait_bounds)] use std::future::Future; use std::pin::pin; use std::task::*; pub fn block_on(fut: impl Future) -> T { let mut fut = pin!(fut); let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { Poll::Pending => {} Poll::Ready(t) => break t, } } } fn main() { block_on(async_main()); } async fn call(f: &impl async Fn() -> T) -> T { f().await } async fn call_once(f: impl async FnOnce() -> T) -> T { f().await } #[derive(Debug)] #[allow(unused)] struct Hello(i32); async fn async_main() { // Capture something by-ref { let x = Hello(0); let c = async || { println!("{x:?}"); }; call(&c).await; call_once(c).await; let x = &Hello(1); let c = async || { println!("{x:?}"); }; call(&c).await; call_once(c).await; } // Capture something and consume it (force to `AsyncFnOnce`) { let x = Hello(2); let c = async || { println!("{x:?}"); drop(x); }; call_once(c).await; } // Capture something with `move`, don't consume it { let x = Hello(3); let c = async move || { println!("{x:?}"); }; call(&c).await; call_once(c).await; let x = &Hello(4); let c = async move || { println!("{x:?}"); }; call(&c).await; call_once(c).await; } // Capture something with `move`, also consume it (so `AsyncFnOnce`) { let x = Hello(5); let c = async move || { println!("{x:?}"); drop(x); }; call_once(c).await; } fn force_fnonce(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T { f } // Capture something with `move`, but infer to `AsyncFnOnce` { let x = Hello(6); let c = force_fnonce(async move || { println!("{x:?}"); }); call_once(c).await; let x = &Hello(7); let c = force_fnonce(async move || { println!("{x:?}"); }); call_once(c).await; } // Capture something by-ref, but infer to `AsyncFnOnce` { let x = Hello(8); let c = force_fnonce(async || { println!("{x:?}"); }); call_once(c).await; let x = &Hello(9); let c = force_fnonce(async || { println!("{x:?}"); }); call_once(c).await; } }