Rollup merge of #119222 - eholk:into-async-iterator, r=compiler-errors,dtolnay
Add `IntoAsyncIterator` This introduces the `IntoAsyncIterator` trait and uses it in the desugaring of the unstable `for await` loop syntax. This is mostly added for symmetry with `Iterator` and `IntoIterator`. r? `@compiler-errors` cc `@rust-lang/libs-api,` `@rust-lang/wg-async`
This commit is contained in:
commit
eef023c806
@ -1814,7 +1814,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
arena_vec![self; head],
|
||||
)
|
||||
}
|
||||
ForLoopKind::ForAwait => self.arena.alloc(head),
|
||||
// ` unsafe { Pin::new_unchecked(&mut into_async_iter(<head>)) }`
|
||||
ForLoopKind::ForAwait => {
|
||||
// `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
|
||||
let iter = self.expr_call_lang_item_fn(
|
||||
head_span,
|
||||
hir::LangItem::IntoAsyncIterIntoIter,
|
||||
arena_vec![self; head],
|
||||
);
|
||||
let iter = self.expr_mut_addr_of(head_span, iter);
|
||||
// `Pin::new_unchecked(...)`
|
||||
let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
|
||||
head_span,
|
||||
hir::LangItem::PinNewUnchecked,
|
||||
arena_vec![self; iter],
|
||||
));
|
||||
// `unsafe { ... }`
|
||||
let iter = self.arena.alloc(self.expr_unsafe(iter));
|
||||
iter
|
||||
}
|
||||
};
|
||||
|
||||
let match_expr = self.arena.alloc(self.expr_match(
|
||||
|
@ -308,6 +308,7 @@ language_item_table! {
|
||||
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
AsyncIteratorPollNext, sym::async_iterator_poll_next, async_iterator_poll_next, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
|
||||
IntoAsyncIterIntoIter, sym::into_async_iter_into_iter, into_async_iter_into_iter, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
|
||||
|
||||
Option, sym::Option, option_type, Target::Enum, GenericRequirement::None;
|
||||
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
|
||||
|
@ -135,3 +135,26 @@ impl<T> Poll<Option<T>> {
|
||||
#[lang = "AsyncGenFinished"]
|
||||
pub const FINISHED: Self = Poll::Ready(None);
|
||||
}
|
||||
|
||||
/// Convert something into an async iterator
|
||||
#[unstable(feature = "async_iterator", issue = "79024")]
|
||||
pub trait IntoAsyncIterator {
|
||||
/// The type of the item yielded by the iterator
|
||||
type Item;
|
||||
/// The type of the resulting iterator
|
||||
type IntoAsyncIter: AsyncIterator<Item = Self::Item>;
|
||||
|
||||
/// Converts `self` into an async iterator
|
||||
#[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")]
|
||||
fn into_async_iter(self) -> Self::IntoAsyncIter;
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_iterator", issue = "79024")]
|
||||
impl<I: AsyncIterator> IntoAsyncIterator for I {
|
||||
type Item = I::Item;
|
||||
type IntoAsyncIter = I;
|
||||
|
||||
fn into_async_iter(self) -> Self::IntoAsyncIter {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -124,5 +124,5 @@
|
||||
mod async_iter;
|
||||
mod from_iter;
|
||||
|
||||
pub use async_iter::AsyncIterator;
|
||||
pub use async_iter::{AsyncIterator, IntoAsyncIterator};
|
||||
pub use from_iter::{from_iter, FromIter};
|
||||
|
17
library/core/tests/async_iter/mod.rs
Normal file
17
library/core/tests/async_iter/mod.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use core::async_iter::{self, AsyncIterator, IntoAsyncIterator};
|
||||
use core::pin::pin;
|
||||
use core::task::Poll;
|
||||
|
||||
#[test]
|
||||
fn into_async_iter() {
|
||||
let async_iter = async_iter::from_iter(0..3);
|
||||
let mut async_iter = pin!(async_iter.into_async_iter());
|
||||
|
||||
let waker = core::task::Waker::noop();
|
||||
let mut cx = &mut core::task::Context::from_waker(&waker);
|
||||
|
||||
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(0)));
|
||||
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(1)));
|
||||
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(2)));
|
||||
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(None));
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
#![feature(array_windows)]
|
||||
#![feature(ascii_char)]
|
||||
#![feature(ascii_char_variants)]
|
||||
#![feature(async_iter_from_iter)]
|
||||
#![feature(async_iterator)]
|
||||
#![feature(bigint_helper_methods)]
|
||||
#![feature(cell_update)]
|
||||
#![feature(const_align_offset)]
|
||||
@ -55,6 +57,7 @@
|
||||
#![feature(maybe_uninit_write_slice)]
|
||||
#![feature(maybe_uninit_uninit_array_transpose)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(noop_waker)]
|
||||
#![feature(numfmt)]
|
||||
#![feature(num_midpoint)]
|
||||
#![feature(isqrt)]
|
||||
@ -125,6 +128,7 @@ mod any;
|
||||
mod array;
|
||||
mod ascii;
|
||||
mod asserting;
|
||||
mod async_iter;
|
||||
mod atomic;
|
||||
mod bool;
|
||||
mod cell;
|
||||
|
@ -33,7 +33,14 @@ error[E0223]: ambiguous associated type
|
||||
--> $DIR/issue-109071.rs:15:22
|
||||
|
|
||||
LL | fn T() -> Option<Self::Item> {}
|
||||
| ^^^^^^^^^^ help: use fully-qualified syntax: `<Windows<T> as IntoIterator>::Item`
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: use fully-qualified syntax
|
||||
|
|
||||
LL | fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {}
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
LL | fn T() -> Option<<Windows<T> as IntoIterator>::Item> {}
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -5,22 +5,17 @@ LL | let iter = core::async_iter::from_iter(0..3);
|
||||
| ---- move occurs because `iter` has type `FromIter<std::ops::Range<i32>>`, which does not implement the `Copy` trait
|
||||
LL | let mut count = 0;
|
||||
LL | for await i in iter {
|
||||
| -------------------
|
||||
| | |
|
||||
| | value moved here
|
||||
| inside of this loop
|
||||
| ---- `iter` moved due to this method call
|
||||
...
|
||||
LL | for await i in iter {
|
||||
| ^^^^ value used here after move
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
note: `into_async_iter` takes ownership of the receiver `self`, which moves `iter`
|
||||
--> $SRC_DIR/core/src/async_iter/async_iter.rs:LL:COL
|
||||
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||
|
|
||||
LL | for await i in iter.clone() {
|
||||
| ++++++++
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | for await i in ref iter {
|
||||
| +++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -2,7 +2,14 @@ error[E0223]: ambiguous associated type
|
||||
--> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38
|
||||
|
|
||||
LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
|
||||
| ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: use fully-qualified syntax
|
||||
|
|
||||
LL | impl<S> Foo for Bar<S> where for<'a> <&'a S as IntoAsyncIterator>::Item: Foo {}
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
LL | impl<S> Foo for Bar<S> where for<'a> <&'a S as IntoIterator>::Item: Foo {}
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -2,7 +2,14 @@ error[E0223]: ambiguous associated type
|
||||
--> $DIR/issue-110052.rs:6:30
|
||||
|
|
||||
LL | for<'iter> dyn Validator<<&'iter I>::Item>:,
|
||||
| ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: use fully-qualified syntax
|
||||
|
|
||||
LL | for<'iter> dyn Validator<<&'iter I as IntoAsyncIterator>::Item>:,
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
LL | for<'iter> dyn Validator<<&'iter I as IntoIterator>::Item>:,
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user