diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0920de48eb87e..0ca603d3a1917 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -762,7 +762,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let features = match await_kind { FutureKind::Future => None, - FutureKind::AsyncIterator => Some(self.allow_for_await.clone()), + FutureKind::Stream => Some(self.allow_for_await.clone()), }; let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features); let gen_future_span = self.mark_span_with_reason( @@ -816,9 +816,9 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], ), - FutureKind::AsyncIterator => self.expr_call_lang_item_fn( + FutureKind::Stream => self.expr_call_lang_item_fn( span, - hir::LangItem::AsyncIteratorPollNext, + hir::LangItem::AsyncStreamPollNext, arena_vec![self; new_unchecked, get_context], ), }; @@ -910,8 +910,8 @@ impl<'hir> LoweringContext<'_, 'hir> { arena_vec![self; *expr], ), // Not needed for `for await` because we expect to have already called - // `IntoAsyncIterator::into_async_iter` on it. - FutureKind::AsyncIterator => expr, + // `IntoStream::into_stream` on it. + FutureKind::Stream => expr, }; // match { @@ -1621,7 +1621,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ForLoopKind::ForAwait => { // we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this - // to make_lowered_await with `FutureKind::AsyncIterator` which will generator + // to make_lowered_await with `FutureKind::Stream` which will generator // calls to `poll_next`. In user code, this would probably be a call to // `Pin::as_mut` but here it's easy enough to do `new_unchecked`. @@ -1635,7 +1635,7 @@ impl<'hir> LoweringContext<'_, 'hir> { )); // `unsafe { ... }` let iter = self.arena.alloc(self.expr_unsafe(iter)); - let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator); + let kind = self.make_lowered_await(head_span, iter, FutureKind::Stream); self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span }) } }; @@ -1670,12 +1670,12 @@ impl<'hir> LoweringContext<'_, 'hir> { arena_vec![self; head], ) } - // ` unsafe { Pin::new_unchecked(&mut into_async_iter()) }` + // ` unsafe { Pin::new_unchecked(&mut into_stream()) }` ForLoopKind::ForAwait => { - // `::core::async_iter::IntoAsyncIterator::into_async_iter()` + // `::core::stream::IntoStream::into_stream()` let iter = self.expr_call_lang_item_fn( head_span, - hir::LangItem::IntoAsyncIterIntoIter, + hir::LangItem::IntoAsyncStreamIntoStream, arena_vec![self; head], ); let iter = self.expr_mut_addr_of(head_span, iter); @@ -2096,7 +2096,7 @@ impl<'hir> LoweringContext<'_, 'hir> { enum FutureKind { /// We are awaiting a normal future Future, - /// We are awaiting something that's known to be an AsyncIterator (i.e. we are in the header of + /// We are awaiting something that's known to be an Stream (i.e. we are in the header of /// a `for await` loop) - AsyncIterator, + Stream, } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 057fe65d0afad..002a589b3b98d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -131,7 +131,7 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Lrc<[Symbol]>, allow_gen_future: Lrc<[Symbol]>, - allow_async_iterator: Lrc<[Symbol]>, + allow_async_stream: Lrc<[Symbol]>, allow_for_await: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. @@ -177,10 +177,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { [sym::gen_future].into() }, - allow_for_await: [sym::async_iterator].into(), + allow_for_await: [sym::async_stream].into(), // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller` // interact with `gen`/`async gen` blocks - allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), + allow_async_stream: [sym::gen_future, sym::async_stream].into(), generics_def_id_map: Default::default(), host_param_id: None, } @@ -1924,7 +1924,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { CoroutineKind::Async { return_impl_trait_id, .. } => (return_impl_trait_id, None), CoroutineKind::Gen { return_impl_trait_id, .. } => (return_impl_trait_id, None), CoroutineKind::AsyncGen { return_impl_trait_id, .. } => { - (return_impl_trait_id, Some(self.allow_async_iterator.clone())) + (return_impl_trait_id, Some(self.allow_async_stream.clone())) } }; @@ -1986,7 +1986,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (assoc_ty_name, trait_lang_item) = match coro { CoroutineKind::Async { .. } => (sym::Output, hir::LangItem::Future), CoroutineKind::Gen { .. } => (sym::Item, hir::LangItem::Iterator), - CoroutineKind::AsyncGen { .. } => (sym::Item, hir::LangItem::AsyncIterator), + CoroutineKind::AsyncGen { .. } => (sym::Item, hir::LangItem::AsyncStream), }; let bound_args = self.arena.alloc(hir::GenericArgs { diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 1cc1f11b3c858..7972ffa25d3f0 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -212,7 +212,7 @@ language_item_table! { Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0); Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); - AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0); + AsyncStream, sym::async_stream, async_stream_trait, Target::Trait, GenericRequirement::Exact(0); CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None; Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1); Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; @@ -307,8 +307,8 @@ language_item_table! { Context, sym::Context, context, Target::Struct, GenericRequirement::None; 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); + AsyncStreamPollNext, sym::async_stream_poll_next, async_stream_poll_next, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); + IntoAsyncStreamIntoStream, sym::into_async_stream_into_stream, into_async_stream_into_stream, 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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7b0138d50baed..1687931121303 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -429,8 +429,8 @@ symbols! { async_fn_in_trait, async_fn_track_caller, async_for_loop, - async_iterator, - async_iterator_poll_next, + async_stream, + async_stream_poll_next, atomic, atomic_mod, atomics, @@ -899,7 +899,7 @@ symbols! { instruction_set, integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below integral, - into_async_iter_into_iter, + into_async_stream_into_stream, into_future, into_iter, intra_doc_pointers, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index caf9470b4c646..5fb133390aac9 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -214,7 +214,7 @@ pub(super) trait GoalKind<'tcx>: goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - fn consider_builtin_async_iterator_candidate( + fn consider_builtin_async_stream_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; @@ -577,8 +577,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_future_candidate(self, goal) } else if lang_items.iterator_trait() == Some(trait_def_id) { G::consider_builtin_iterator_candidate(self, goal) - } else if lang_items.async_iterator_trait() == Some(trait_def_id) { - G::consider_builtin_async_iterator_candidate(self, goal) + } else if lang_items.async_stream_trait() == Some(trait_def_id) { + G::consider_builtin_async_stream_candidate(self, goal) } else if lang_items.coroutine_trait() == Some(trait_def_id) { G::consider_builtin_coroutine_candidate(self, goal) } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) { diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index ccee6f8eb29b9..135b316fb73d6 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -525,7 +525,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ) } - fn consider_builtin_async_iterator_candidate( + fn consider_builtin_async_stream_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index be07927568446..b26fbdee33e78 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -377,7 +377,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - fn consider_builtin_async_iterator_candidate( + fn consider_builtin_async_stream_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index abbc2066eac16..321764674421e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1829,7 +1829,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( lang_items.coroutine_trait(), lang_items.future_trait(), lang_items.iterator_trait(), - lang_items.async_iterator_trait(), + lang_items.async_stream_trait(), lang_items.fn_trait(), lang_items.fn_mut_trait(), lang_items.fn_once_trait(), @@ -2051,8 +2051,8 @@ fn confirm_select_candidate<'cx, 'tcx>( confirm_future_candidate(selcx, obligation, data) } else if lang_items.iterator_trait() == Some(trait_def_id) { confirm_iterator_candidate(selcx, obligation, data) - } else if lang_items.async_iterator_trait() == Some(trait_def_id) { - confirm_async_iterator_candidate(selcx, obligation, data) + } else if lang_items.async_stream_trait() == Some(trait_def_id) { + confirm_async_stream_candidate(selcx, obligation, data) } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() { if obligation.predicate.self_ty().is_closure() { confirm_closure_candidate(selcx, obligation, data) @@ -2218,7 +2218,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( .with_addl_obligations(obligations) } -fn confirm_async_iterator_candidate<'cx, 'tcx>( +fn confirm_async_stream_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, nested: Vec>, @@ -2236,12 +2236,12 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( gen_sig, ); - debug!(?obligation, ?gen_sig, ?obligations, "confirm_async_iterator_candidate"); + debug!(?obligation, ?gen_sig, ?obligations, "confirm_async_stream_candidate"); let tcx = selcx.tcx(); - let iter_def_id = tcx.require_lang_item(LangItem::AsyncIterator, None); + let iter_def_id = tcx.require_lang_item(LangItem::AsyncStream, None); - let (trait_ref, yield_ty) = super::util::async_iterator_trait_ref_and_outputs( + let (trait_ref, yield_ty) = super::util::async_stream_trait_ref_and_outputs( tcx, iter_def_id, obligation.predicate.self_ty(), diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 342b12ba49848..27666e9046b7e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -112,8 +112,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_future_candidates(obligation, &mut candidates); } else if lang_items.iterator_trait() == Some(def_id) { self.assemble_iterator_candidates(obligation, &mut candidates); - } else if lang_items.async_iterator_trait() == Some(def_id) { - self.assemble_async_iterator_candidates(obligation, &mut candidates); + } else if lang_items.async_stream_trait() == Some(def_id) { + self.assemble_async_stream_candidates(obligation, &mut candidates); } self.assemble_closure_candidates(obligation, &mut candidates); @@ -257,7 +257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_async_iterator_candidates( + fn assemble_async_stream_candidates( &mut self, obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 74f388e53a3c9..d95eacfc45b3e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -99,7 +99,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } AsyncIteratorCandidate => { - let vtable_iterator = self.confirm_async_iterator_candidate(obligation)?; + let vtable_iterator = self.confirm_async_stream_candidate(obligation)?; ImplSource::Builtin(BuiltinImplSource::Misc, vtable_iterator) } @@ -818,7 +818,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(nested) } - fn confirm_async_iterator_candidate( + fn confirm_async_stream_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { @@ -830,11 +830,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bug!("closure candidate for non-closure {:?}", obligation); }; - debug!(?obligation, ?coroutine_def_id, ?args, "confirm_async_iterator_candidate"); + debug!(?obligation, ?coroutine_def_id, ?args, "confirm_async_stream_candidate"); let gen_sig = args.as_coroutine().sig(); - let (trait_ref, _) = super::util::async_iterator_trait_ref_and_outputs( + let (trait_ref, _) = super::util::async_stream_trait_ref_and_outputs( self.tcx(), obligation.predicate.def_id(), obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(), diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index c40ed10e52ff3..b20ebed367fcf 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -320,14 +320,14 @@ pub fn iterator_trait_ref_and_outputs<'tcx>( (trait_ref, sig.yield_ty) } -pub fn async_iterator_trait_ref_and_outputs<'tcx>( +pub fn async_stream_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, - async_iterator_def_id: DefId, + async_stream_def_id: DefId, self_ty: Ty<'tcx>, sig: ty::GenSig<'tcx>, ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); - let trait_ref = ty::TraitRef::new(tcx, async_iterator_def_id, [self_ty]); + let trait_ref = ty::TraitRef::new(tcx, async_stream_def_id, [self_ty]); (trait_ref, sig.yield_ty) } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 81d5304b81265..de3534f9d0782 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -271,7 +271,7 @@ fn resolve_associated_item<'tcx>( debug_assert!(tcx.defaultness(trait_item_id).has_value()); Some(Instance::new(trait_item_id, rcvr_args)) } - } else if Some(trait_ref.def_id) == lang_items.async_iterator_trait() { + } else if Some(trait_ref.def_id) == lang_items.async_stream_trait() { let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else { bug!() }; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 6977681e5a397..a1db87659366e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -164,6 +164,7 @@ use core::ops::{ }; use core::pin::Pin; use core::ptr::{self, NonNull, Unique}; +use core::stream::Stream; use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] @@ -2153,8 +2154,8 @@ where } } -#[unstable(feature = "async_iterator", issue = "79024")] -impl AsyncIterator for Box { +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for Box { type Item = S::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -2166,6 +2167,19 @@ impl AsyncIterator for Box { } } +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for Box { + type Item = I::Item; + + async fn next(&mut self) -> Option { + (&mut **self).next().await + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 78629b39d34b1..e6120d3bcd7c0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -108,6 +108,7 @@ #![feature(ascii_char)] #![feature(assert_matches)] #![feature(async_iterator)] +#![feature(async_stream)] #![feature(coerce_unsized)] #![feature(const_align_of_val)] #![feature(const_box)] diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index db71a286b6dd0..de3d8e0d0e194 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -1,19 +1,19 @@ -use crate::ops::DerefMut; -use crate::pin::Pin; -use crate::task::{Context, Poll}; - /// A trait for dealing with asynchronous iterators. /// +/// This trait is an alternative to the [`Stream`] trait. Both traits are +/// currently being evaluated on nightly with the intent to stabilize only one. +/// /// This is the main async iterator trait. For more about the concept of async iterators /// generally, please see the [module-level documentation]. In particular, you /// may want to know how to [implement `AsyncIterator`][impl]. /// /// [module-level documentation]: index.html /// [impl]: index.html#implementing-async-iterator +/// [`Stream`]: crate::stream::Stream #[unstable(feature = "async_iterator", issue = "79024")] #[must_use = "async iterators do nothing unless polled"] #[doc(alias = "Stream")] -#[lang = "async_iterator"] +#[allow(async_fn_in_trait)] pub trait AsyncIterator { /// The type of items yielded by the async iterator. type Item; @@ -21,34 +21,7 @@ pub trait AsyncIterator { /// Attempt to pull out the next value of this async iterator, registering the /// current task for wakeup if the value is not yet available, and returning /// `None` if the async iterator is exhausted. - /// - /// # Return value - /// - /// There are several possible return values, each indicating a distinct - /// async iterator state: - /// - /// - `Poll::Pending` means that this async iterator's next value is not ready - /// yet. Implementations will ensure that the current task will be notified - /// when the next value may be ready. - /// - /// - `Poll::Ready(Some(val))` means that the async iterator has successfully - /// produced a value, `val`, and may produce further values on subsequent - /// `poll_next` calls. - /// - /// - `Poll::Ready(None)` means that the async iterator has terminated, and - /// `poll_next` should not be invoked again. - /// - /// # Panics - /// - /// Once an async iterator has finished (returned `Ready(None)` from `poll_next`), calling its - /// `poll_next` method again may panic, block forever, or cause other kinds of - /// problems; the `AsyncIterator` trait places no requirements on the effects of - /// such a call. However, as the `poll_next` method is not marked `unsafe`, - /// Rust's usual rules apply: calls must never cause undefined behavior - /// (memory corruption, incorrect use of `unsafe` functions, or the like), - /// regardless of the async iterator's state. - #[cfg_attr(not(bootstrap), lang = "async_iterator_poll_next")] - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + async fn next(&mut self) -> Option; /// Returns the bounds on the remaining length of the async iterator. /// @@ -83,28 +56,11 @@ pub trait AsyncIterator { } #[unstable(feature = "async_iterator", issue = "79024")] -impl AsyncIterator for &mut S { - type Item = S::Item; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - S::poll_next(Pin::new(&mut **self), cx) - } - - fn size_hint(&self) -> (usize, Option) { - (**self).size_hint() - } -} - -#[unstable(feature = "async_iterator", issue = "79024")] -impl

AsyncIterator for Pin

-where - P: DerefMut, - P::Target: AsyncIterator, -{ - type Item = ::Item; +impl AsyncIterator for &mut I { + type Item = I::Item; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - ::poll_next(self.as_deref_mut(), cx) + async fn next(&mut self) -> Option { + (**self).next().await } fn size_hint(&self) -> (usize, Option) { @@ -112,30 +68,6 @@ where } } -#[unstable(feature = "async_gen_internals", issue = "none")] -impl Poll> { - /// A helper function for internal desugaring -- produces `Ready(Some(t))`, - /// which corresponds to the async iterator yielding a value. - #[unstable(feature = "async_gen_internals", issue = "none")] - #[lang = "AsyncGenReady"] - pub fn async_gen_ready(t: T) -> Self { - Poll::Ready(Some(t)) - } - - /// A helper constant for internal desugaring -- produces `Pending`, - /// which corresponds to the async iterator pending on an `.await`. - #[unstable(feature = "async_gen_internals", issue = "none")] - #[lang = "AsyncGenPending"] - // FIXME(gen_blocks): This probably could be deduplicated. - pub const PENDING: Self = Poll::Pending; - - /// A helper constant for internal desugaring -- produces `Ready(None)`, - /// which corresponds to the async iterator finishing its iteration. - #[unstable(feature = "async_gen_internals", issue = "none")] - #[lang = "AsyncGenFinished"] - pub const FINISHED: Self = Poll::Ready(None); -} - /// Convert something into an async iterator #[unstable(feature = "async_iterator", issue = "79024")] pub trait IntoAsyncIterator { @@ -145,7 +77,6 @@ pub trait IntoAsyncIterator { type IntoAsyncIter: AsyncIterator; /// Converts `self` into an async iterator - #[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")] fn into_async_iter(self) -> Self::IntoAsyncIter; } diff --git a/library/core/src/async_iter/from_iter.rs b/library/core/src/async_iter/from_iter.rs index 3180187afc8c9..4573c8e804812 100644 --- a/library/core/src/async_iter/from_iter.rs +++ b/library/core/src/async_iter/from_iter.rs @@ -1,7 +1,4 @@ -use crate::pin::Pin; - use crate::async_iter::AsyncIterator; -use crate::task::{Context, Poll}; /// An async iterator that was created from iterator. /// @@ -28,8 +25,8 @@ pub fn from_iter(iter: I) -> FromIter { impl AsyncIterator for FromIter { type Item = I::Item; - fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - Poll::Ready(self.iter.next()) + async fn next(&mut self) -> Option { + self.iter.next() } fn size_hint(&self) -> (usize, Option) { diff --git a/library/core/src/async_iter/mod.rs b/library/core/src/async_iter/mod.rs index e1f1c9075823d..ad51084ac315a 100644 --- a/library/core/src/async_iter/mod.rs +++ b/library/core/src/async_iter/mod.rs @@ -30,20 +30,12 @@ //! [`AsyncIterator`] looks like this: //! //! ``` -//! # use core::task::{Context, Poll}; -//! # use core::pin::Pin; //! trait AsyncIterator { //! type Item; -//! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; +//! async fn next(&mut self) -> Option; //! } //! ``` //! -//! Unlike `Iterator`, `AsyncIterator` makes a distinction between the [`poll_next`] -//! method which is used when implementing an `AsyncIterator`, and a (to-be-implemented) -//! `next` method which is used when consuming an async iterator. Consumers of `AsyncIterator` -//! only need to consider `next`, which when called, returns a future which -//! yields `Option`. -//! //! The future returned by `next` will yield `Some(Item)` as long as there are //! elements, and once they've all been exhausted, will yield `None` to indicate //! that iteration is finished. If we're waiting on something asynchronous to @@ -53,11 +45,10 @@ //! again may or may not eventually yield `Some(Item)` again at some point. //! //! [`AsyncIterator`]'s full definition includes a number of other methods as well, -//! but they are default methods, built on top of [`poll_next`], and so you get +//! but they are default methods, built on top of [`next`], and so you get //! them for free. //! -//! [`Poll`]: super::task::Poll -//! [`poll_next`]: AsyncIterator::poll_next +//! [`next`]: AsyncIterator::next //! //! # Implementing Async Iterator //! @@ -70,8 +61,6 @@ //! ```no_run //! #![feature(async_iterator)] //! # use core::async_iter::AsyncIterator; -//! # use core::task::{Context, Poll}; -//! # use core::pin::Pin; //! //! // First, the struct: //! @@ -82,7 +71,7 @@ //! //! // we want our count to start at one, so let's add a new() method to help. //! // This isn't strictly necessary, but is convenient. Note that we start -//! // `count` at zero, we'll see why in `poll_next()`'s implementation below. +//! // `count` at zero, we'll see why in `next()`'s implementation below. //! impl Counter { //! fn new() -> Counter { //! Counter { count: 0 } @@ -95,16 +84,16 @@ //! // we will be counting with usize //! type Item = usize; //! -//! // poll_next() is the only required method -//! fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { +//! // next() is the only required method +//! async fn next(&mut self) -> Option { //! // Increment our count. This is why we started at zero. //! self.count += 1; //! //! // Check to see if we've finished counting or not. //! if self.count < 6 { -//! Poll::Ready(Some(self.count)) +//! Some(self.count) //! } else { -//! Poll::Ready(None) +//! None //! } //! } //! } @@ -113,7 +102,7 @@ //! # Laziness //! //! Async iterators are *lazy*. This means that just creating an async iterator doesn't -//! _do_ a whole lot. Nothing really happens until you call `poll_next`. This is +//! _do_ a whole lot. Nothing really happens until you call `next`. This is //! sometimes a source of confusion when creating an async iterator solely for its side //! effects. The compiler will warn us about this kind of behavior: //! diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 24ad78efa83b1..4210e4742bfd2 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -382,6 +382,8 @@ pub mod panic; pub mod panicking; pub mod pin; pub mod result; +#[unstable(feature = "async_stream", issue = "79024")] +pub mod stream; pub mod sync; pub mod fmt; diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 37859212c0ee3..39cb7092e98f1 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -5,6 +5,7 @@ use crate::future::Future; use crate::ops::{Deref, DerefMut}; use crate::pin::Pin; use crate::ptr::{NonNull, Unique}; +use crate::stream::Stream; use crate::task::{Context, Poll}; /// A marker trait which represents "panic safe" types in Rust. @@ -298,8 +299,8 @@ impl Future for AssertUnwindSafe { } } -#[unstable(feature = "async_iterator", issue = "79024")] -impl AsyncIterator for AssertUnwindSafe { +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for AssertUnwindSafe { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -311,3 +312,16 @@ impl AsyncIterator for AssertUnwindSafe { self.0.size_hint() } } + +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for AssertUnwindSafe { + type Item = I::Item; + + async fn next(&mut self) -> Option { + self.0.next().await + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} diff --git a/library/core/src/stream/from_iter.rs b/library/core/src/stream/from_iter.rs new file mode 100644 index 0000000000000..e435b3e788432 --- /dev/null +++ b/library/core/src/stream/from_iter.rs @@ -0,0 +1,38 @@ +use crate::pin::Pin; + +use crate::stream::Stream; +use crate::task::{Context, Poll}; + +/// A stream that was created from an iterator. +/// +/// This stream is created by the [`from_iter`] function. +/// See it documentation for more. +/// +/// [`from_iter`]: fn.from_iter.html +#[unstable(feature = "async_stream_from_iter", issue = "81798")] +#[derive(Clone, Debug)] +pub struct FromIter { + iter: I, +} + +#[unstable(feature = "async_stream_from_iter", issue = "81798")] +impl Unpin for FromIter {} + +/// Converts an iterator into an async iterator. +#[unstable(feature = "async_stream_from_iter", issue = "81798")] +pub fn from_iter(iter: I) -> FromIter { + FromIter { iter: iter.into_iter() } +} + +#[unstable(feature = "async_stream_from_iter", issue = "81798")] +impl Stream for FromIter { + type Item = I::Item; + + fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} diff --git a/library/core/src/stream/mod.rs b/library/core/src/stream/mod.rs new file mode 100644 index 0000000000000..9c1df290df7e9 --- /dev/null +++ b/library/core/src/stream/mod.rs @@ -0,0 +1,128 @@ +//! Composable asynchronous iteration. +//! +//! If you've found yourself with an asynchronous collection of some kind, +//! and needed to perform an operation on the elements of said collection, +//! you'll quickly run into 'streams'. streams are heavily used in +//! idiomatic asynchronous Rust code, so it's worth becoming familiar with them. +//! +//! Before explaining more, let's talk about how this module is structured: +//! +//! # Organization +//! +//! This module is largely organized by type: +//! +//! * [Traits] are the core portion: these traits define what kind of streams +//! exist and what you can do with them. The methods of these traits are worth +//! putting some extra study time into. +//! * Functions provide some helpful ways to create some basic streams. +//! * Structs are often the return types of the various methods on this +//! module's traits. You'll usually want to look at the method that creates +//! the `struct`, rather than the `struct` itself. For more detail about why, +//! see '[Implementing Stream](#implementing-stream)'. +//! +//! [Traits]: #traits +//! +//! That's it! Let's dig into streams. +//! +//! # Streams +//! +//! The heart and soul of this module is the [`Stream`] trait. The core of +//! [`Stream`] looks like this: +//! +//! ``` +//! # use core::task::{Context, Poll}; +//! # use core::pin::Pin; +//! trait Stream { +//! type Item; +//! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; +//! } +//! ``` +//! +//! Unlike `Iterator`, `Stream` makes a distinction between the [`poll_next`] +//! method which is used when implementing an `Stream`, and a (to-be-implemented) +//! `next` method which is used when consuming an stream. Consumers of `Stream` +//! only need to consider `next`, which when called, returns a future which +//! yields `Option`. +//! +//! The future returned by `next` will yield `Some(Item)` as long as there are +//! elements, and once they've all been exhausted, will yield `None` to indicate +//! that iteration is finished. If we're waiting on something asynchronous to +//! resolve, the future will wait until the stream is ready to yield again. +//! +//! Individual streams may choose to resume iteration, and so calling `next` +//! again may or may not eventually yield `Some(Item)` again at some point. +//! +//! [`Stream`]'s full definition includes a number of other methods as well, +//! but they are default methods, built on top of [`poll_next`], and so you get +//! them for free. +//! +//! [`Poll`]: super::task::Poll +//! [`poll_next`]: Stream::poll_next +//! +//! # Implementing Stream +//! +//! Creating an stream of your own involves two steps: creating a `struct` to +//! hold the stream's state, and then implementing [`Stream`] for that +//! `struct`. +//! +//! Let's make an stream named `Counter` which counts from `1` to `5`: +//! +//! ```no_run +//! #![feature(async_stream)] +//! # use core::stream::Stream; +//! # use core::task::{Context, Poll}; +//! # use core::pin::Pin; +//! +//! // First, the struct: +//! +//! /// An stream which counts from one to five +//! struct Counter { +//! count: usize, +//! } +//! +//! // we want our count to start at one, so let's add a new() method to help. +//! // This isn't strictly necessary, but is convenient. Note that we start +//! // `count` at zero, we'll see why in `poll_next()`'s implementation below. +//! impl Counter { +//! fn new() -> Counter { +//! Counter { count: 0 } +//! } +//! } +//! +//! // Then, we implement `Stream` for our `Counter`: +//! +//! impl Stream for Counter { +//! // we will be counting with usize +//! type Item = usize; +//! +//! // poll_next() is the only required method +//! fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { +//! // Increment our count. This is why we started at zero. +//! self.count += 1; +//! +//! // Check to see if we've finished counting or not. +//! if self.count < 6 { +//! Poll::Ready(Some(self.count)) +//! } else { +//! Poll::Ready(None) +//! } +//! } +//! } +//! ``` +//! +//! # Laziness +//! +//! Streams are *lazy*. This means that just creating an stream doesn't +//! _do_ a whole lot. Nothing really happens until you call `poll_next`. This is +//! sometimes a source of confusion when creating an stream solely for its side +//! effects. The compiler will warn us about this kind of behavior: +//! +//! ```text +//! warning: unused result that must be used: streams do nothing unless polled +//! ``` + +mod from_iter; +mod stream; + +pub use from_iter::{from_iter, FromIter}; +pub use stream::{IntoStream, Stream}; diff --git a/library/core/src/stream/stream.rs b/library/core/src/stream/stream.rs new file mode 100644 index 0000000000000..e22e102015fb5 --- /dev/null +++ b/library/core/src/stream/stream.rs @@ -0,0 +1,163 @@ +use crate::ops::DerefMut; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// A trait for dealing with asynchronous streams. +/// +/// This trait is an alternative to the [`AsyncIterator`] trait. Both traits are +/// currently being evaluated on nightly with the intent to stabilize only one. +/// +/// This is the main stream trait. For more about the concept of streams +/// generally, please see the [module-level documentation]. In particular, you +/// may want to know how to [implement `Stream`][impl]. +/// +/// [module-level documentation]: index.html +/// [impl]: index.html#implementing-stream +/// [`AsyncIterator`]: crate::async_iter::AsyncIterator +#[unstable(feature = "async_stream", issue = "79024")] +#[must_use = "streams do nothing unless polled"] +#[cfg_attr(not(bootstrap), lang = "async_stream")] +pub trait Stream { + /// The type of items yielded by the stream. + type Item; + + /// Attempt to pull out the next value of this stream, registering the + /// current task for wakeup if the value is not yet available, and returning + /// `None` if the stream is exhausted. + /// + /// # Return value + /// + /// There are several possible return values, each indicating a distinct + /// stream state: + /// + /// - `Poll::Pending` means that this stream's next value is not ready + /// yet. Implementations will ensure that the current task will be notified + /// when the next value may be ready. + /// + /// - `Poll::Ready(Some(val))` means that the stream has successfully + /// produced a value, `val`, and may produce further values on subsequent + /// `poll_next` calls. + /// + /// - `Poll::Ready(None)` means that the stream has terminated, and + /// `poll_next` should not be invoked again. + /// + /// # Panics + /// + /// Once an stream has finished (returned `Ready(None)` from `poll_next`), calling its + /// `poll_next` method again may panic, block forever, or cause other kinds of + /// problems; the `Asyncstream` trait places no requirements on the effects of + /// such a call. However, as the `poll_next` method is not marked `unsafe`, + /// Rust's usual rules apply: calls must never cause undefined behavior + /// (memory corruption, incorrect use of `unsafe` functions, or the like), + /// regardless of the stream's state. + #[cfg_attr(not(bootstrap), lang = "async_stream_poll_next")] + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + + /// Returns the bounds on the remaining length of the stream. + /// + /// Specifically, `size_hint()` returns a tuple where the first element + /// is the lower bound, and the second element is the upper bound. + /// + /// The second half of the tuple that is returned is an [Option]<[usize]>. + /// A [`None`] here means that either there is no known upper bound, or the + /// upper bound is larger than [`usize`]. + /// + /// # Implementation notes + /// + /// It is not enforced that an stream implementation yields the declared + /// number of elements. A buggy stream may yield less than the lower bound + /// or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the stream, but must not be + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// The default implementation returns (0, [None]) which is correct for any + /// stream. + #[inline] + fn size_hint(&self) -> (usize, Option) { + (0, None) + } +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for &mut S { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + S::poll_next(Pin::new(&mut **self), cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl

Stream for Pin

+where + P: DerefMut, + P::Target: Stream, +{ + type Item = ::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ::poll_next(self.as_deref_mut(), cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +#[unstable(feature = "async_gen_internals", issue = "none")] +impl Poll> { + /// A helper function for internal desugaring -- produces `Ready(Some(t))`, + /// which corresponds to the stream yielding a value. + #[unstable(feature = "async_gen_internals", issue = "none")] + #[lang = "AsyncGenReady"] + pub fn async_gen_ready(t: T) -> Self { + Poll::Ready(Some(t)) + } + + /// A helper constant for internal desugaring -- produces `Pending`, + /// which corresponds to the stream pending on an `.await`. + #[unstable(feature = "async_gen_internals", issue = "none")] + #[lang = "AsyncGenPending"] + // FIXME(gen_blocks): This probably could be deduplicated. + pub const PENDING: Self = Poll::Pending; + + /// A helper constant for internal desugaring -- produces `Ready(None)`, + /// which corresponds to the stream finishing its iteration. + #[unstable(feature = "async_gen_internals", issue = "none")] + #[lang = "AsyncGenFinished"] + pub const FINISHED: Self = Poll::Ready(None); +} + +/// Convert something into an stream +#[unstable(feature = "async_stream", issue = "79024")] +pub trait IntoStream { + /// The type of the item yielded by the stream + type Item; + /// The type of the resulting stream + type IntoStream: Stream; + + /// Converts `self` into an stream + #[cfg_attr(not(bootstrap), lang = "into_async_stream_into_stream")] + fn into_stream(self) -> Self::IntoStream; +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl IntoStream for I { + type Item = I::Item; + type IntoStream = I; + + fn into_stream(self) -> Self::IntoStream { + self + } +} diff --git a/library/core/tests/async_iter/mod.rs b/library/core/tests/async_iter/mod.rs index 4f425d7286d09..296f74982d97c 100644 --- a/library/core/tests/async_iter/mod.rs +++ b/library/core/tests/async_iter/mod.rs @@ -1,16 +1,17 @@ use core::async_iter::{self, AsyncIterator, IntoAsyncIterator}; +use core::future::Future; 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 mut async_iter = async_iter.into_async_iter(); let mut cx = &mut core::task::Context::from_waker(core::task::Waker::noop()); - 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)); + assert_eq!(pin!(async_iter.next()).poll(&mut cx), Poll::Ready(Some(0))); + assert_eq!(pin!(async_iter.next()).poll(&mut cx), Poll::Ready(Some(1))); + assert_eq!(pin!(async_iter.next()).poll(&mut cx), Poll::Ready(Some(2))); + assert_eq!(pin!(async_iter.next()).poll(&mut cx), Poll::Ready(None)); } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 13fb97fdc7f3e..cdaddd8bfe0f0 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -4,8 +4,10 @@ #![feature(array_windows)] #![feature(ascii_char)] #![feature(ascii_char_variants)] -#![feature(async_iter_from_iter)] #![feature(async_iterator)] +#![feature(async_iter_from_iter)] +#![feature(async_stream)] +#![feature(async_stream_from_iter)] #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(const_align_offset)] @@ -161,6 +163,7 @@ mod simd; mod slice; mod str; mod str_lossy; +mod stream; mod task; mod time; mod tuple; diff --git a/library/core/tests/stream/mod.rs b/library/core/tests/stream/mod.rs new file mode 100644 index 0000000000000..e59fab4066b57 --- /dev/null +++ b/library/core/tests/stream/mod.rs @@ -0,0 +1,17 @@ +use core::pin::pin; +use core::stream::{self, IntoStream, Stream}; +use core::task::Poll; + +#[test] +fn into_stream() { + let stream = stream::from_iter(0..3); + let mut stream = pin!(stream.into_stream()); + + let waker = core::task::Waker::noop(); + let mut cx = &mut core::task::Context::from_waker(&waker); + + assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(Some(0))); + assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(Some(1))); + assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(Some(2))); + assert_eq!(stream.as_mut().poll_next(&mut cx), Poll::Ready(None)); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 568645ddf7311..694484defb755 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -367,6 +367,7 @@ // tidy-alphabetical-start #![feature(assert_matches)] #![feature(async_iterator)] +#![feature(async_stream)] #![feature(c_variadic)] #![feature(cfg_accessible)] #![feature(cfg_eval)] @@ -531,6 +532,8 @@ pub use core::pin; pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] pub use core::result; +#[unstable(feature = "async_stream", issue = "79024")] +pub use core::stream; #[stable(feature = "i128", since = "1.26.0")] #[allow(deprecated, deprecated_in_future)] pub use core::u128; 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 b8366b15a8ae4..1e8ebe0fe6ff4 100644 --- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr @@ -42,6 +42,8 @@ LL | fn T() -> Option< as IntoAsyncIterator>::Item> {} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | fn T() -> Option< as IntoIterator>::Item> {} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | fn T() -> Option< as IntoStream>::Item> {} + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/feature-async-for-loop.rs b/tests/ui/async-await/feature-async-for-loop.rs index 42247dd14b0d1..ff13908523b5c 100644 --- a/tests/ui/async-await/feature-async-for-loop.rs +++ b/tests/ui/async-await/feature-async-for-loop.rs @@ -1,11 +1,11 @@ // edition:2021 // gate-test-async_for_loop -#![feature(async_iter_from_iter, async_iterator)] +#![feature(async_stream_from_iter, async_stream)] fn f() { let _ = async { - for await _i in core::async_iter::from_iter(0..3) { + for await _i in core::stream::from_iter(0..3) { //~^ ERROR `for await` loops are experimental } }; @@ -14,7 +14,7 @@ fn f() { #[cfg(FALSE)] fn g() { let _ = async { - for await _i in core::async_iter::from_iter(0..3) { + for await _i in core::stream::from_iter(0..3) { //~^ ERROR `for await` loops are experimental } }; diff --git a/tests/ui/async-await/feature-async-for-loop.stderr b/tests/ui/async-await/feature-async-for-loop.stderr index 62ddc4222b85e..d9c0721a71de3 100644 --- a/tests/ui/async-await/feature-async-for-loop.stderr +++ b/tests/ui/async-await/feature-async-for-loop.stderr @@ -1,7 +1,7 @@ error[E0658]: `for await` loops are experimental --> $DIR/feature-async-for-loop.rs:8:13 | -LL | for await _i in core::async_iter::from_iter(0..3) { +LL | for await _i in core::stream::from_iter(0..3) { | ^^^^^ | = note: see issue #118898 for more information @@ -11,7 +11,7 @@ LL | for await _i in core::async_iter::from_iter(0..3) { error[E0658]: `for await` loops are experimental --> $DIR/feature-async-for-loop.rs:17:13 | -LL | for await _i in core::async_iter::from_iter(0..3) { +LL | for await _i in core::stream::from_iter(0..3) { | ^^^^^ | = note: see issue #118898 for more information diff --git a/tests/ui/async-await/for-await-consumes-iter.rs b/tests/ui/async-await/for-await-consumes-iter.rs index 65bb9e88448ff..b2035aa5a94af 100644 --- a/tests/ui/async-await/for-await-consumes-iter.rs +++ b/tests/ui/async-await/for-await-consumes-iter.rs @@ -1,12 +1,12 @@ // edition: 2021 -#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker)] +#![feature(async_stream, async_stream_from_iter, const_waker, async_for_loop, noop_waker)] use std::future::Future; // a test to make sure `for await` consumes the iterator async fn real_main() { - let iter = core::async_iter::from_iter(0..3); + let iter = core::stream::from_iter(0..3); let mut count = 0; for await i in iter { } diff --git a/tests/ui/async-await/for-await-consumes-iter.stderr b/tests/ui/async-await/for-await-consumes-iter.stderr index a3e5bbcabf5d0..d93b5245eafa9 100644 --- a/tests/ui/async-await/for-await-consumes-iter.stderr +++ b/tests/ui/async-await/for-await-consumes-iter.stderr @@ -1,8 +1,8 @@ error[E0382]: use of moved value: `iter` --> $DIR/for-await-consumes-iter.rs:14:20 | -LL | let iter = core::async_iter::from_iter(0..3); - | ---- move occurs because `iter` has type `FromIter>`, which does not implement the `Copy` trait +LL | let iter = core::stream::from_iter(0..3); + | ---- move occurs because `iter` has type `std::stream::FromIter>`, which does not implement the `Copy` trait LL | let mut count = 0; LL | for await i in iter { | ---- `iter` moved due to this method call @@ -10,8 +10,8 @@ LL | for await i in iter { LL | for await i in iter { | ^^^^ value used here after move | -note: `into_async_iter` takes ownership of the receiver `self`, which moves `iter` - --> $SRC_DIR/core/src/async_iter/async_iter.rs:LL:COL +note: `into_stream` takes ownership of the receiver `self`, which moves `iter` + --> $SRC_DIR/core/src/stream/stream.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() { diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs index b1a382958a157..27066d23694ea 100644 --- a/tests/ui/async-await/for-await-passthrough.rs +++ b/tests/ui/async-await/for-await-passthrough.rs @@ -1,13 +1,13 @@ // run-pass // edition: 2024 // compile-flags: -Zunstable-options -#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker, +#![feature(async_stream, async_stream_from_iter, const_waker, async_for_loop, noop_waker, gen_blocks)] use std::future::Future; -async gen fn async_iter() -> i32 { - let iter = core::async_iter::from_iter(0..3); +async gen fn stream() -> i32 { + let iter = core::stream::from_iter(0..3); for await i in iter { yield i + 1; } @@ -16,7 +16,7 @@ async gen fn async_iter() -> i32 { // make sure a simple for await loop works async fn real_main() { let mut count = 1; - for await i in async_iter() { + for await i in stream() { assert_eq!(i, count); count += 1; } diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs index 00dbdfb2389d5..dec6b9a2f4e33 100644 --- a/tests/ui/async-await/for-await.rs +++ b/tests/ui/async-await/for-await.rs @@ -1,12 +1,12 @@ // run-pass // edition: 2021 -#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker)] +#![feature(async_stream, async_stream_from_iter, const_waker, async_for_loop, noop_waker)] use std::future::Future; // make sure a simple for await loop works async fn real_main() { - let iter = core::async_iter::from_iter(0..3); + let iter = core::stream::from_iter(0..3); let mut count = 0; for await i in iter { assert_eq!(i, count); diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs index 9ccc8ee41f667..bbe0af5255028 100644 --- a/tests/ui/coroutine/async-gen-deduce-yield.rs +++ b/tests/ui/coroutine/async-gen-deduce-yield.rs @@ -1,11 +1,11 @@ // compile-flags: --edition 2024 -Zunstable-options // check-pass -#![feature(async_iterator, gen_blocks)] +#![feature(async_stream, gen_blocks)] -use std::async_iter::AsyncIterator; +use std::stream::Stream; -fn deduce() -> impl AsyncIterator { +fn deduce() -> impl Stream { async gen { yield Default::default(); } diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index 80c0b69a6f7ed..c28f666c9c515 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -1,9 +1,9 @@ // compile-flags: --edition 2024 -Zunstable-options // check-pass -#![feature(async_iterator, gen_blocks, noop_waker)] +#![feature(async_stream, gen_blocks, noop_waker)] -use std::{async_iter::AsyncIterator, pin::pin, task::{Context, Waker}}; +use std::{stream::Stream, pin::pin, task::{Context, Waker}}; async gen fn gen_fn() -> &'static str { yield "hello" @@ -12,5 +12,5 @@ async gen fn gen_fn() -> &'static str { pub fn main() { let async_iterator = pin!(gen_fn()); let ctx = &mut Context::from_waker(Waker::noop()); - async_iterator.poll_next(ctx); + stream.poll_next(ctx); } diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs index 604156b4d373f..64cce95d3eba9 100644 --- a/tests/ui/coroutine/async_gen_fn_iter.rs +++ b/tests/ui/coroutine/async_gen_fn_iter.rs @@ -2,7 +2,7 @@ // compile-flags: -Zunstable-options // run-pass -#![feature(gen_blocks, async_iterator)] +#![feature(gen_blocks, async_stream)] #![feature(noop_waker)] // make sure that a ridiculously simple async gen fn works as an iterator. @@ -45,14 +45,14 @@ async fn async_main() { use std::pin::{Pin, pin}; use std::task::*; -use std::async_iter::AsyncIterator; +use std::stream::Stream; use std::future::Future; -trait AsyncIterExt { +trait StreamExt { fn next(&mut self) -> Next<'_, Self>; } -impl AsyncIterExt for T { +impl StreamExt for T { fn next(&mut self) -> Next<'_, Self> { Next { s: self } } @@ -62,7 +62,7 @@ struct Next<'s, S: ?Sized> { s: &'s mut S, } -impl<'s, S: AsyncIterator> Future for Next<'s, S> where S: Unpin { +impl<'s, S: Stream> Future for Next<'s, S> where S: Unpin { type Output = Option; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { 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 cabaa76a8867d..60d430efcb37e 100644 --- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -10,6 +10,8 @@ LL | impl Foo for Bar where for<'a> <&'a S as IntoAsyncIterator>::Item: Fo | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | impl Foo for Bar where for<'a> <&'a S as IntoIterator>::Item: Foo {} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | impl Foo for Bar where for<'a> <&'a S as IntoStream>::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 5eb10d9a30e86..ae372d96619f3 100644 --- a/tests/ui/typeck/issue-110052.stderr +++ b/tests/ui/typeck/issue-110052.stderr @@ -10,6 +10,8 @@ LL | for<'iter> dyn Validator<<&'iter I as IntoAsyncIterator>::Item>:, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | for<'iter> dyn Validator<<&'iter I as IntoIterator>::Item>:, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | for<'iter> dyn Validator<<&'iter I as IntoStream>::Item>:, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error