diff options
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/lang_items.rs | 1 | ||||
| -rw-r--r-- | library/core/src/async_iter/async_iter.rs | 23 | ||||
| -rw-r--r-- | library/core/src/async_iter/mod.rs | 2 | ||||
| -rw-r--r-- | library/core/tests/async_iter/mod.rs | 17 | ||||
| -rw-r--r-- | library/core/tests/lib.rs | 4 | ||||
| -rw-r--r-- | tests/ui/associated-inherent-types/issue-109071.no_gate.stderr | 9 | ||||
| -rw-r--r-- | tests/ui/async-await/for-await-consumes-iter.stderr | 13 | ||||
| -rw-r--r-- | tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr | 9 | ||||
| -rw-r--r-- | tests/ui/typeck/issue-110052.stderr | 9 |
10 files changed, 93 insertions, 14 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5fa04dda8be..1f6d47ab453 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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( diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 7691cd11c4f..3f3b57ba94f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -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; diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index a7512ef6a24..db71a286b6d 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -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 + } +} diff --git a/library/core/src/async_iter/mod.rs b/library/core/src/async_iter/mod.rs index 0c6f637711b..e1f1c907582 100644 --- a/library/core/src/async_iter/mod.rs +++ b/library/core/src/async_iter/mod.rs @@ -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}; diff --git a/library/core/tests/async_iter/mod.rs b/library/core/tests/async_iter/mod.rs new file mode 100644 index 00000000000..0c30bd1dfea --- /dev/null +++ b/library/core/tests/async_iter/mod.rs @@ -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)); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index fabdd4ee25d..b53cf459244 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -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; diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr index 866a53f57fc..2fceeb15ea9 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -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 diff --git a/tests/ui/async-await/for-await-consumes-iter.stderr b/tests/ui/async-await/for-await-consumes-iter.stderr index 48b2e8a51d8..a3e5bbcabf5 100644 --- a/tests/ui/async-await/for-await-consumes-iter.stderr +++ b/tests/ui/async-await/for-await-consumes-iter.stderr @@ -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 diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr index c0f0c414227..cabaa76a886 100644 --- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -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 diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr index b25b6c0c0b7..5eb10d9a30e 100644 --- a/tests/ui/typeck/issue-110052.stderr +++ b/tests/ui/typeck/issue-110052.stderr @@ -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 |
