libcore: Add iter::from_generator which is like iter::from_fn, but for coroutines instead of functions

This commit is contained in:
Vadim Petrochenkov 2022-04-21 23:47:39 +03:00
parent 490324f7b2
commit 5bf23f64cc
9 changed files with 67 additions and 34 deletions

View file

@ -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<F: Fn()>(pub F);
impl<F: Fn()> OnDrop<F> {
@ -135,26 +130,6 @@ impl<F: Fn()> Drop for OnDrop<F> {
}
}
struct IterFromGenerator<G>(G);
impl<G: Generator<Return = ()> + Unpin> Iterator for IterFromGenerator<G> {
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
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<G: Generator<Return = ()> + Unpin>(
generator: G,
) -> impl Iterator<Item = G::Yield> {
IterFromGenerator(generator)
}
// See comments in src/librustc_middle/lib.rs
#[doc(hidden)]
pub fn __noop_fix_for_27438() {}

View file

@ -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)]

View file

@ -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

View file

@ -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")]

View file

@ -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};

View file

@ -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<G: Generator<Return = ()> + Unpin>(
generator: G,
) -> impl Iterator<Item = G::Yield> {
FromGenerator(generator)
}
struct FromGenerator<G>(G);
impl<G: Generator<Return = ()> + Unpin> Iterator for FromGenerator<G> {
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match Pin::new(&mut self.0).resume(()) {
GeneratorState::Yielded(n) => Some(n),
GeneratorState::Complete(()) => None,
}
}
}

View file

@ -43,13 +43,13 @@ LL | require_send(send_fut);
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= 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<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
= 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<Output = ()>`
note: required by a bound in `require_send`
--> $DIR/issue-68112.rs:11:25

View file

@ -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<Output = ()>, ()}`
= 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<Output = ()>`
= note: required because it appears within the type `impl Future<Output = ()>`
note: required by a bound in `gimme_send`

View file

@ -7,11 +7,11 @@ LL | | x
LL | | }
| |_^ the trait `Generator<ResumeTy>` 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<ResumeTy, Yield = ()>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<ResumeTy>>::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<ResumeTy, Yield = ()>,
| ^^^^^^^^^^ required by this bound in `from_generator`
| ^^^^^^^^^^ required by this bound in `std::future::from_generator`
error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
--> $DIR/async.rs:7:29