diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/ui/async-await/async-closure.rs | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/async-await/async-closure.rs')
-rw-r--r-- | tests/ui/async-await/async-closure.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/tests/ui/async-await/async-closure.rs b/tests/ui/async-await/async-closure.rs new file mode 100644 index 000000000..12d66b19e --- /dev/null +++ b/tests/ui/async-await/async-closure.rs @@ -0,0 +1,100 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +// edition:2018 +// aux-build:arc_wake.rs + +#![feature(async_closure)] + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc<Self>) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc<Self>) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool); + +fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } + +impl Future for WakeOnceThenComplete { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.0 { + Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn async_closure(x: u8) -> impl Future<Output = u8> { + (async move |x: u8| -> u8 { + wake_and_yield_once().await; + x + })(x) +} + +fn async_closure_in_unsafe_block(x: u8) -> impl Future<Output = u8> { + (unsafe { + async move |x: u8| unsafe_fn(unsafe_async_fn(x).await) + })(x) +} + +async unsafe fn unsafe_async_fn(x: u8) -> u8 { + wake_and_yield_once().await; + x +} + +unsafe fn unsafe_fn(x: u8) -> u8 { + x +} + +fn test_future_yields_once_then_returns<F, Fut>(f: F) +where + F: FnOnce(u8) -> Fut, + Fut: Future<Output = u8>, +{ + let mut fut = Box::pin(f(9)); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx)); + assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx)); +} + +fn main() { + macro_rules! test { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns($fn_name); + )* } + } + + test! { + async_closure, + async_closure_in_unsafe_block, + } +} |