blob: f77123751e1d530395f0bf1f5c4b1c6cd656b0ad [file] [edit]
//@ edition: 2024
//@ run-pass
#![allow(incomplete_features)]
#![feature(async_iterator, gen_blocks, move_expr)]
use std::async_iter::AsyncIterator;
use std::cell::Cell;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll, Waker};
struct PendingOnce {
pending: bool,
}
impl PendingOnce {
fn new() -> Self {
Self { pending: true }
}
}
impl Future for PendingOnce {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
if self.pending {
self.pending = false;
cx.waker().wake_by_ref();
Poll::Pending
} else {
Poll::Ready(())
}
}
}
fn poll_next<I: AsyncIterator>(iter: Pin<&mut I>) -> Poll<Option<I::Item>> {
let cx = &mut Context::from_waker(Waker::noop());
AsyncIterator::poll_next(iter, cx)
}
fn ready_next<I: AsyncIterator>(iter: Pin<&mut I>) -> Option<I::Item> {
match poll_next(iter) {
Poll::Ready(item) => item,
Poll::Pending => panic!("async iterator unexpectedly returned pending"),
}
}
fn main() {
let created = Cell::new(0);
let mut iter = Box::pin(async gen {
let n = move({
created.set(created.get() + 1);
created.get()
});
yield n;
yield n + 1;
});
assert_eq!(created.get(), 1);
assert_eq!(ready_next(iter.as_mut()), Some(1));
assert_eq!(ready_next(iter.as_mut()), Some(2));
assert_eq!(ready_next(iter.as_mut()), None);
let x = Arc::new(String::from("hello"));
assert_eq!(Arc::strong_count(&x), 1);
let mut iter = Box::pin(async gen {
let value = move(x.clone());
yield Arc::strong_count(&value);
PendingOnce::new().await;
yield Arc::strong_count(&value);
});
assert_eq!(Arc::strong_count(&x), 2);
assert_eq!(ready_next(iter.as_mut()), Some(2));
assert!(matches!(poll_next(iter.as_mut()), Poll::Pending));
assert_eq!(ready_next(iter.as_mut()), Some(2));
drop(iter);
assert_eq!(Arc::strong_count(&x), 1);
let y = Arc::new(String::from("nested"));
let weak = Arc::downgrade(&y);
let mut iter = Box::pin(async gen {
let mut inner = Box::pin(async gen {
let value = move(move(y.clone()));
yield Arc::strong_count(&value);
});
yield ready_next(inner.as_mut()).unwrap();
});
assert_eq!(weak.strong_count(), 2);
assert_eq!(ready_next(iter.as_mut()), Some(2));
drop(iter);
assert_eq!(weak.strong_count(), 1);
assert_eq!(&*y, "nested");
let z = Arc::new(String::from("async gen move"));
assert_eq!(Arc::strong_count(&z), 1);
let mut iter = Box::pin(async gen move {
let value = move(z.clone());
yield Arc::strong_count(&value);
});
assert_eq!(Arc::strong_count(&z), 2);
assert_eq!(ready_next(iter.as_mut()), Some(2));
drop(iter);
assert_eq!(Arc::strong_count(&z), 1);
}