Skip to content

Commit 5bf23f6

Browse files
committed
libcore: Add iter::from_generator which is like iter::from_fn, but for coroutines instead of functions
1 parent 490324f commit 5bf23f6

File tree

9 files changed

+67
-34
lines changed

9 files changed

+67
-34
lines changed

compiler/rustc_data_structures/src/lib.rs

-25
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#![feature(control_flow_enum)]
1414
#![feature(core_intrinsics)]
1515
#![feature(extend_one)]
16-
#![feature(generator_trait)]
17-
#![feature(generators)]
1816
#![feature(let_else)]
1917
#![feature(hash_raw_entry)]
2018
#![feature(hasher_prefixfree_extras)]
@@ -114,9 +112,6 @@ pub mod unhash;
114112
pub use ena::undo_log;
115113
pub use ena::unify;
116114

117-
use std::ops::{Generator, GeneratorState};
118-
use std::pin::Pin;
119-
120115
pub struct OnDrop<F: Fn()>(pub F);
121116

122117
impl<F: Fn()> OnDrop<F> {
@@ -135,26 +130,6 @@ impl<F: Fn()> Drop for OnDrop<F> {
135130
}
136131
}
137132

138-
struct IterFromGenerator<G>(G);
139-
140-
impl<G: Generator<Return = ()> + Unpin> Iterator for IterFromGenerator<G> {
141-
type Item = G::Yield;
142-
143-
fn next(&mut self) -> Option<Self::Item> {
144-
match Pin::new(&mut self.0).resume(()) {
145-
GeneratorState::Yielded(n) => Some(n),
146-
GeneratorState::Complete(_) => None,
147-
}
148-
}
149-
}
150-
151-
/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`.
152-
pub fn iter_from_generator<G: Generator<Return = ()> + Unpin>(
153-
generator: G,
154-
) -> impl Iterator<Item = G::Yield> {
155-
IterFromGenerator(generator)
156-
}
157-
158133
// See comments in src/librustc_middle/lib.rs
159134
#[doc(hidden)]
160135
pub fn __noop_fix_for_27438() {}

compiler/rustc_metadata/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(drain_filter)]
44
#![feature(generators)]
55
#![feature(generic_associated_types)]
6+
#![feature(iter_from_generator)]
67
#![feature(let_chains)]
78
#![feature(let_else)]
89
#![feature(nll)]

compiler/rustc_metadata/src/rmeta/encoder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::rmeta::*;
44

55
use rustc_data_structures::fingerprint::Fingerprint;
66
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
7-
use rustc_data_structures::iter_from_generator;
87
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
98
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
109
use rustc_hir as hir;
@@ -39,6 +38,7 @@ use rustc_span::{
3938
use rustc_target::abi::VariantIdx;
4039
use std::borrow::Borrow;
4140
use std::hash::Hash;
41+
use std::iter;
4242
use std::num::NonZeroUsize;
4343
use tracing::{debug, trace};
4444

@@ -1134,7 +1134,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11341134
// Encode this here because we don't do it in encode_def_ids.
11351135
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
11361136
} else {
1137-
record_array!(self.tables.children[def_id] <- iter_from_generator(|| {
1137+
record_array!(self.tables.children[def_id] <- iter::from_generator(|| {
11381138
for item_id in md.item_ids {
11391139
match tcx.hir().item(*item_id).kind {
11401140
// Foreign items are planted into their parent modules

library/core/src/iter/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,12 @@ pub use self::traits::Iterator;
362362
)]
363363
pub use self::range::Step;
364364

365+
#[unstable(
366+
feature = "iter_from_generator",
367+
issue = "43122",
368+
reason = "generators are unstable"
369+
)]
370+
pub use self::sources::from_generator;
365371
#[stable(feature = "iter_empty", since = "1.2.0")]
366372
pub use self::sources::{empty, Empty};
367373
#[stable(feature = "iter_from_fn", since = "1.34.0")]

library/core/src/iter/sources.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod empty;
22
mod from_fn;
3+
mod from_generator;
34
mod once;
45
mod once_with;
56
mod repeat;
@@ -21,6 +22,13 @@ pub use self::repeat_with::{repeat_with, RepeatWith};
2122
#[stable(feature = "iter_from_fn", since = "1.34.0")]
2223
pub use self::from_fn::{from_fn, FromFn};
2324

25+
#[unstable(
26+
feature = "iter_from_generator",
27+
issue = "43122",
28+
reason = "generators are unstable"
29+
)]
30+
pub use self::from_generator::from_generator;
31+
2432
#[stable(feature = "iter_successors", since = "1.34.0")]
2533
pub use self::successors::{successors, Successors};
2634

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use crate::ops::{Generator, GeneratorState};
2+
use crate::pin::Pin;
3+
4+
/// Creates a new iterator where each iteration calls the provided generator.
5+
///
6+
/// Similar to [`iter::from_fn`].
7+
///
8+
/// [`iter::from_fn`]: crate::iter::from_fn
9+
///
10+
/// # Examples
11+
///
12+
/// ```
13+
/// #![feature(generators)]
14+
/// #![feature(iter_from_generator)]
15+
///
16+
/// let it = std::iter::from_generator(|| {
17+
/// yield 1;
18+
/// yield 2;
19+
/// yield 3;
20+
/// });
21+
/// let v: Vec<_> = it.collect();
22+
/// assert_eq!(v, [1, 2, 3]);
23+
/// ```
24+
#[inline]
25+
#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
26+
pub fn from_generator<G: Generator<Return = ()> + Unpin>(
27+
generator: G,
28+
) -> impl Iterator<Item = G::Yield> {
29+
FromGenerator(generator)
30+
}
31+
32+
struct FromGenerator<G>(G);
33+
34+
impl<G: Generator<Return = ()> + Unpin> Iterator for FromGenerator<G> {
35+
type Item = G::Yield;
36+
37+
fn next(&mut self) -> Option<Self::Item> {
38+
match Pin::new(&mut self.0).resume(()) {
39+
GeneratorState::Yielded(n) => Some(n),
40+
GeneratorState::Complete(()) => None,
41+
}
42+
}
43+
}

src/test/ui/async-await/issue-68112.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ LL | require_send(send_fut);
4343
= help: the trait `Sync` is not implemented for `RefCell<i32>`
4444
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
4545
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
46-
= note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
46+
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
4747
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
4848
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
4949
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
5050
= note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
5151
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
52-
= note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
52+
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
5353
= note: required because it appears within the type `impl Future<Output = ()>`
5454
note: required by a bound in `require_send`
5555
--> $DIR/issue-68112.rs:11:25

src/test/ui/async-await/partial-drop-partial-reinit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | async fn foo() {
1313
= note: required because it appears within the type `(NotSend,)`
1414
= note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future<Output = ()>, ()}`
1515
= note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]`
16-
= note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>`
16+
= 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]>`
1717
= note: required because it appears within the type `impl Future<Output = ()>`
1818
= note: required because it appears within the type `impl Future<Output = ()>`
1919
note: required by a bound in `gimme_send`

src/test/ui/chalkify/bugs/async.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ LL | | x
77
LL | | }
88
| |_^ the trait `Generator<ResumeTy>` is not implemented for `[static generator@$DIR/async.rs:7:29: 9:2]`
99
|
10-
note: required by a bound in `from_generator`
10+
note: required by a bound in `std::future::from_generator`
1111
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
1212
|
1313
LL | T: Generator<ResumeTy, Yield = ()>,
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `from_generator`
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `std::future::from_generator`
1515

1616
error[E0280]: the requirement `<[static generator@$DIR/async.rs:7:29: 9:2] as Generator<ResumeTy>>::Yield == ()` is not satisfied
1717
--> $DIR/async.rs:7:29
@@ -22,11 +22,11 @@ LL | | x
2222
LL | | }
2323
| |_^
2424
|
25-
note: required by a bound in `from_generator`
25+
note: required by a bound in `std::future::from_generator`
2626
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
2727
|
2828
LL | T: Generator<ResumeTy, Yield = ()>,
29-
| ^^^^^^^^^^ required by this bound in `from_generator`
29+
| ^^^^^^^^^^ required by this bound in `std::future::from_generator`
3030

3131
error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
3232
--> $DIR/async.rs:7:29

0 commit comments

Comments
 (0)