From 5bf23f64cce3877434da31e74e376186986903a2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 21 Apr 2022 23:47:39 +0300 Subject: [PATCH] libcore: Add `iter::from_generator` which is like `iter::from_fn`, but for coroutines instead of functions --- compiler/rustc_data_structures/src/lib.rs | 25 ----------- compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- library/core/src/iter/mod.rs | 6 +++ library/core/src/iter/sources.rs | 8 ++++ .../core/src/iter/sources/from_generator.rs | 43 +++++++++++++++++++ src/test/ui/async-await/issue-68112.stderr | 4 +- .../partial-drop-partial-reinit.stderr | 2 +- src/test/ui/chalkify/bugs/async.stderr | 8 ++-- 9 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 library/core/src/iter/sources/from_generator.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 76ae17f28c613..0d072046d58ff 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -13,8 +13,6 @@ #![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(extend_one)] -#![feature(generator_trait)] -#![feature(generators)] #![feature(let_else)] #![feature(hash_raw_entry)] #![feature(hasher_prefixfree_extras)] @@ -114,9 +112,6 @@ pub mod unhash; pub use ena::undo_log; pub use ena::unify; -use std::ops::{Generator, GeneratorState}; -use std::pin::Pin; - pub struct OnDrop(pub F); impl OnDrop { @@ -135,26 +130,6 @@ impl Drop for OnDrop { } } -struct IterFromGenerator(G); - -impl + Unpin> Iterator for IterFromGenerator { - type Item = G::Yield; - - fn next(&mut self) -> Option { - match Pin::new(&mut self.0).resume(()) { - GeneratorState::Yielded(n) => Some(n), - GeneratorState::Complete(_) => None, - } - } -} - -/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`. -pub fn iter_from_generator + Unpin>( - generator: G, -) -> impl Iterator { - IterFromGenerator(generator) -} - // See comments in src/librustc_middle/lib.rs #[doc(hidden)] pub fn __noop_fix_for_27438() {} diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 4c5d13dfa6c8c..eb008fd2693ba 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -3,6 +3,7 @@ #![feature(drain_filter)] #![feature(generators)] #![feature(generic_associated_types)] +#![feature(iter_from_generator)] #![feature(let_chains)] #![feature(let_else)] #![feature(nll)] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 63103061c9c29..339d2fc0867ae 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -4,7 +4,6 @@ use crate::rmeta::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_data_structures::iter_from_generator; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; @@ -39,6 +38,7 @@ use rustc_span::{ use rustc_target::abi::VariantIdx; use std::borrow::Borrow; use std::hash::Hash; +use std::iter; use std::num::NonZeroUsize; use tracing::{debug, trace}; @@ -1134,7 +1134,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode this here because we don't do it in encode_def_ids. record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); } else { - record_array!(self.tables.children[def_id] <- iter_from_generator(|| { + record_array!(self.tables.children[def_id] <- iter::from_generator(|| { for item_id in md.item_ids { match tcx.hir().item(*item_id).kind { // Foreign items are planted into their parent modules diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 22b76ea66ff15..15362d2330acc 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -362,6 +362,12 @@ pub use self::traits::Iterator; )] pub use self::range::Step; +#[unstable( + feature = "iter_from_generator", + issue = "43122", + reason = "generators are unstable" +)] +pub use self::sources::from_generator; #[stable(feature = "iter_empty", since = "1.2.0")] pub use self::sources::{empty, Empty}; #[stable(feature = "iter_from_fn", since = "1.34.0")] diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs index 37b6f2e2565b2..d34772cd304ff 100644 --- a/library/core/src/iter/sources.rs +++ b/library/core/src/iter/sources.rs @@ -1,5 +1,6 @@ mod empty; mod from_fn; +mod from_generator; mod once; mod once_with; mod repeat; @@ -21,6 +22,13 @@ pub use self::repeat_with::{repeat_with, RepeatWith}; #[stable(feature = "iter_from_fn", since = "1.34.0")] pub use self::from_fn::{from_fn, FromFn}; +#[unstable( + feature = "iter_from_generator", + issue = "43122", + reason = "generators are unstable" +)] +pub use self::from_generator::from_generator; + #[stable(feature = "iter_successors", since = "1.34.0")] pub use self::successors::{successors, Successors}; diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs new file mode 100644 index 0000000000000..8e7cbd34a4f66 --- /dev/null +++ b/library/core/src/iter/sources/from_generator.rs @@ -0,0 +1,43 @@ +use crate::ops::{Generator, GeneratorState}; +use crate::pin::Pin; + +/// Creates a new iterator where each iteration calls the provided generator. +/// +/// Similar to [`iter::from_fn`]. +/// +/// [`iter::from_fn`]: crate::iter::from_fn +/// +/// # Examples +/// +/// ``` +/// #![feature(generators)] +/// #![feature(iter_from_generator)] +/// +/// let it = std::iter::from_generator(|| { +/// yield 1; +/// yield 2; +/// yield 3; +/// }); +/// let v: Vec<_> = it.collect(); +/// assert_eq!(v, [1, 2, 3]); +/// ``` +#[inline] +#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] +pub fn from_generator + Unpin>( + generator: G, +) -> impl Iterator { + FromGenerator(generator) +} + +struct FromGenerator(G); + +impl + Unpin> Iterator for FromGenerator { + type Item = G::Yield; + + fn next(&mut self) -> Option { + match Pin::new(&mut self.0).resume(()) { + GeneratorState::Yielded(n) => Some(n), + GeneratorState::Complete(()) => None, + } + } +} diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index 36b7f2e455867..28d94b14ac914 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -43,13 +43,13 @@ LL | require_send(send_fut); = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` = note: required because it appears within the type `impl Future>>` = note: required because it appears within the type `impl Future>>` = note: required because it appears within the type `impl Future>>` = note: required because it appears within the type `{ResumeTy, impl Future>>, (), i32, Ready}` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` = note: required because it appears within the type `impl Future` note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.stderr index 7c074b07c3d59..a1c4957e9843a 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.stderr @@ -13,7 +13,7 @@ LL | async fn foo() { = note: required because it appears within the type `(NotSend,)` = note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future, ()}` = note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>` = note: required because it appears within the type `impl Future` = note: required because it appears within the type `impl Future` note: required by a bound in `gimme_send` diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr index e6a72c72dd37c..5b7ca8d46cf44 100644 --- a/src/test/ui/chalkify/bugs/async.stderr +++ b/src/test/ui/chalkify/bugs/async.stderr @@ -7,11 +7,11 @@ LL | | x LL | | } | |_^ the trait `Generator` is not implemented for `[static generator@$DIR/async.rs:7:29: 9:2]` | -note: required by a bound in `from_generator` +note: required by a bound in `std::future::from_generator` --> $SRC_DIR/core/src/future/mod.rs:LL:COL | LL | T: Generator, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `from_generator` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `std::future::from_generator` error[E0280]: the requirement `<[static generator@$DIR/async.rs:7:29: 9:2] as Generator>::Yield == ()` is not satisfied --> $DIR/async.rs:7:29 @@ -22,11 +22,11 @@ LL | | x LL | | } | |_^ | -note: required by a bound in `from_generator` +note: required by a bound in `std::future::from_generator` --> $SRC_DIR/core/src/future/mod.rs:LL:COL | LL | T: Generator, - | ^^^^^^^^^^ required by this bound in `from_generator` + | ^^^^^^^^^^ required by this bound in `std::future::from_generator` error[E0280]: the requirement ` as Future>::Output == u32` is not satisfied --> $DIR/async.rs:7:29