Skip to content

Commit fb7192d

Browse files
committed
Add async_iter_next to assist with for await desugaring
1 parent caa63dc commit fb7192d

File tree

5 files changed

+44
-1
lines changed

5 files changed

+44
-1
lines changed

compiler/rustc_hir/src/lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ language_item_table! {
302302
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
303303
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
304304

305+
AsyncIterNext, sym::async_iter_next, async_iter_next, Target::Fn, GenericRequirement::Exact(2);
306+
305307
Option, sym::Option, option_type, Target::Enum, GenericRequirement::None;
306308
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
307309
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ symbols! {
423423
async_closure,
424424
async_fn_in_trait,
425425
async_fn_track_caller,
426+
async_iter_next,
426427
async_iterator,
427428
atomic,
428429
atomic_mod,

library/core/src/async_iter/async_iter.rs

+18
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,21 @@ impl<I: AsyncIterator> IntoAsyncIterator for I {
131131
self
132132
}
133133
}
134+
135+
/// Create a future that returns the next item from an `AsyncIterator`.
136+
///
137+
/// This primarily exists for the compiler to use in desugaring `for await` loops.
138+
#[unstable(feature = "async_iterator", issue = "79024")]
139+
#[cfg_attr(not(bootstrap), lang = "async_iter_next")]
140+
pub fn async_iter_next<'a, I: AsyncIterator>(
141+
iter: Pin<&'a mut I>,
142+
) -> impl core::future::Future<Output = Option<I::Item>> + 'a {
143+
struct Next<'a, I: AsyncIterator>(Pin<&'a mut I>);
144+
impl<'a, I: AsyncIterator> core::future::Future for Next<'a, I> {
145+
type Output = Option<I::Item>;
146+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
147+
I::poll_next(self.0.as_mut(), cx)
148+
}
149+
}
150+
Next(iter)
151+
}

library/core/src/async_iter/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,5 @@
124124
mod async_iter;
125125
mod from_iter;
126126

127-
pub use async_iter::{AsyncIterator, IntoAsyncIterator};
127+
pub use async_iter::{async_iter_next, AsyncIterator, IntoAsyncIterator};
128128
pub use from_iter::{from_iter, FromIter};

library/core/tests/async_iter/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::async_iter::{self, AsyncIterator, IntoAsyncIterator};
2+
use core::future::Future;
23
use core::pin::pin;
34
use core::task::Poll;
45

@@ -25,3 +26,24 @@ fn into_async_iter() {
2526
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(2)));
2627
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(None));
2728
}
29+
30+
#[test]
31+
fn async_iter_next() {
32+
let async_iter = async_iter::from_iter(0..3);
33+
let async_iter = pin!(async_iter.into_async_iter());
34+
35+
let waker = noop_waker::NOOP_WAKER;
36+
let mut cx = &mut core::task::Context::from_waker(&waker);
37+
38+
let mut fut = pin!(core::async_iter::async_iter_next(async_iter));
39+
40+
loop {
41+
match fut.as_mut().poll(&mut cx) {
42+
Poll::Ready(item) => {
43+
assert_eq!(item, Some(0));
44+
return;
45+
}
46+
Poll::Pending => continue,
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)