Skip to content

Commit 044fe0f

Browse files
Add a resume type parameter to Generator
1 parent 0cbcb17 commit 044fe0f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+185
-122
lines changed

src/doc/unstable-book/src/language-features/generators.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ fn main() {
3737
return "foo"
3838
};
3939

40-
match Pin::new(&mut generator).resume() {
40+
match Pin::new(&mut generator).resume(()) {
4141
GeneratorState::Yielded(1) => {}
4242
_ => panic!("unexpected value from resume"),
4343
}
44-
match Pin::new(&mut generator).resume() {
44+
match Pin::new(&mut generator).resume(()) {
4545
GeneratorState::Complete("foo") => {}
4646
_ => panic!("unexpected value from resume"),
4747
}
@@ -71,9 +71,9 @@ fn main() {
7171
};
7272

7373
println!("1");
74-
Pin::new(&mut generator).resume();
74+
Pin::new(&mut generator).resume(());
7575
println!("3");
76-
Pin::new(&mut generator).resume();
76+
Pin::new(&mut generator).resume(());
7777
println!("5");
7878
}
7979
```
@@ -92,10 +92,10 @@ The `Generator` trait in `std::ops` currently looks like:
9292
# use std::ops::GeneratorState;
9393
# use std::pin::Pin;
9494
95-
pub trait Generator {
95+
pub trait Generator<R = ()> {
9696
type Yield;
9797
type Return;
98-
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
98+
fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
9999
}
100100
```
101101

@@ -152,10 +152,6 @@ closure-like semantics. Namely:
152152
* Whenever a generator is dropped it will drop all captured environment
153153
variables.
154154

155-
Note that unlike closures, generators at this time cannot take any arguments.
156-
That is, generators must always look like `|| { ... }`. This restriction may be
157-
lifted at a future date, the design is ongoing!
158-
159155
### Generators as state machines
160156

161157
In the compiler, generators are currently compiled as state machines. Each
@@ -179,8 +175,8 @@ fn main() {
179175
return ret
180176
};
181177

182-
Pin::new(&mut generator).resume();
183-
Pin::new(&mut generator).resume();
178+
Pin::new(&mut generator).resume(());
179+
Pin::new(&mut generator).resume(());
184180
}
185181
```
186182

@@ -205,7 +201,7 @@ fn main() {
205201
type Yield = i32;
206202
type Return = &'static str;
207203

208-
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<i32, &'static str> {
204+
fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
209205
use std::mem;
210206
match mem::replace(&mut *self, __Generator::Done) {
211207
__Generator::Start(s) => {
@@ -228,8 +224,8 @@ fn main() {
228224
__Generator::Start(ret)
229225
};
230226

231-
Pin::new(&mut generator).resume();
232-
Pin::new(&mut generator).resume();
227+
Pin::new(&mut generator).resume(());
228+
Pin::new(&mut generator).resume(());
233229
}
234230
```
235231

src/liballoc/boxed.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,7 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
11031103
#[stable(feature = "pin", since = "1.33.0")]
11041104
impl<T: ?Sized> Unpin for Box<T> {}
11051105

1106+
#[cfg(bootstrap)]
11061107
#[unstable(feature = "generator_trait", issue = "43122")]
11071108
impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
11081109
type Yield = G::Yield;
@@ -1113,6 +1114,7 @@ impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
11131114
}
11141115
}
11151116

1117+
#[cfg(bootstrap)]
11161118
#[unstable(feature = "generator_trait", issue = "43122")]
11171119
impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
11181120
type Yield = G::Yield;
@@ -1123,6 +1125,28 @@ impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
11231125
}
11241126
}
11251127

1128+
#[cfg(not(bootstrap))]
1129+
#[unstable(feature = "generator_trait", issue = "43122")]
1130+
impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
1131+
type Yield = G::Yield;
1132+
type Return = G::Return;
1133+
1134+
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
1135+
G::resume(Pin::new(&mut *self), arg)
1136+
}
1137+
}
1138+
1139+
#[cfg(not(bootstrap))]
1140+
#[unstable(feature = "generator_trait", issue = "43122")]
1141+
impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> {
1142+
type Yield = G::Yield;
1143+
type Return = G::Return;
1144+
1145+
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
1146+
G::resume((*self).as_mut(), arg)
1147+
}
1148+
}
1149+
11261150
#[stable(feature = "futures_api", since = "1.36.0")]
11271151
impl<F: ?Sized + Future + Unpin> Future for Box<F> {
11281152
type Output = F::Output;

src/libcore/ops/generator.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ pub enum GeneratorState<Y, R> {
5050
/// return "foo"
5151
/// };
5252
///
53-
/// match Pin::new(&mut generator).resume() {
53+
/// match Pin::new(&mut generator).resume(()) {
5454
/// GeneratorState::Yielded(1) => {}
5555
/// _ => panic!("unexpected return from resume"),
5656
/// }
57-
/// match Pin::new(&mut generator).resume() {
57+
/// match Pin::new(&mut generator).resume(()) {
5858
/// GeneratorState::Complete("foo") => {}
5959
/// _ => panic!("unexpected return from resume"),
6060
/// }
@@ -67,7 +67,7 @@ pub enum GeneratorState<Y, R> {
6767
#[lang = "generator"]
6868
#[unstable(feature = "generator_trait", issue = "43122")]
6969
#[fundamental]
70-
pub trait Generator {
70+
pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
7171
/// The type of value this generator yields.
7272
///
7373
/// This associated type corresponds to the `yield` expression and the
@@ -110,9 +110,13 @@ pub trait Generator {
110110
/// been returned previously. While generator literals in the language are
111111
/// guaranteed to panic on resuming after `Complete`, this is not guaranteed
112112
/// for all implementations of the `Generator` trait.
113-
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
113+
fn resume(
114+
self: Pin<&mut Self>,
115+
#[cfg(not(bootstrap))] arg: R,
116+
) -> GeneratorState<Self::Yield, Self::Return>;
114117
}
115118

119+
#[cfg(bootstrap)]
116120
#[unstable(feature = "generator_trait", issue = "43122")]
117121
impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
118122
type Yield = G::Yield;
@@ -123,6 +127,7 @@ impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
123127
}
124128
}
125129

130+
#[cfg(bootstrap)]
126131
#[unstable(feature = "generator_trait", issue = "43122")]
127132
impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
128133
type Yield = G::Yield;
@@ -132,3 +137,25 @@ impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
132137
G::resume(Pin::new(&mut *self))
133138
}
134139
}
140+
141+
#[cfg(not(bootstrap))]
142+
#[unstable(feature = "generator_trait", issue = "43122")]
143+
impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
144+
type Yield = G::Yield;
145+
type Return = G::Return;
146+
147+
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
148+
G::resume((*self).as_mut(), arg)
149+
}
150+
}
151+
152+
#[cfg(not(bootstrap))]
153+
#[unstable(feature = "generator_trait", issue = "43122")]
154+
impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
155+
type Yield = G::Yield;
156+
type Return = G::Return;
157+
158+
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
159+
G::resume(Pin::new(&mut *self), arg)
160+
}
161+
}

src/librustc/traits/util.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,10 @@ pub fn generator_trait_ref_and_outputs(
643643
self_ty: Ty<'tcx>,
644644
sig: ty::PolyGenSig<'tcx>,
645645
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
646-
let trait_ref =
647-
ty::TraitRef { def_id: fn_trait_def_id, substs: tcx.mk_substs_trait(self_ty, &[]) };
646+
let trait_ref = ty::TraitRef {
647+
def_id: fn_trait_def_id,
648+
substs: tcx.mk_substs_trait(self_ty, &[tcx.mk_unit().into()]),
649+
};
648650
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
649651
}
650652

src/librustc/ty/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,8 +2350,8 @@ impl<'tcx> ty::Instance<'tcx> {
23502350
]);
23512351
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
23522352

2353-
tcx.mk_fn_sig(iter::once(env_ty),
2354-
ret_ty,
2353+
tcx.mk_fn_sig([env_ty, tcx.mk_unit()].iter(),
2354+
&ret_ty,
23552355
false,
23562356
hir::Unsafety::Normal,
23572357
rustc_target::spec::abi::Abi::Rust

src/librustc_error_codes/error_codes/E0626.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ let mut b = || {
1212
yield (); // ...is still in scope here, when the yield occurs.
1313
println!("{}", a);
1414
};
15-
Pin::new(&mut b).resume();
15+
Pin::new(&mut b).resume(());
1616
```
1717

1818
At present, it is not permitted to have a yield that occurs while a
@@ -31,7 +31,7 @@ let mut b = || {
3131
yield ();
3232
println!("{}", a);
3333
};
34-
Pin::new(&mut b).resume();
34+
Pin::new(&mut b).resume(());
3535
```
3636

3737
This is a very simple case, of course. In more complex cases, we may
@@ -50,7 +50,7 @@ let mut b = || {
5050
yield x; // ...when this yield occurs.
5151
}
5252
};
53-
Pin::new(&mut b).resume();
53+
Pin::new(&mut b).resume(());
5454
```
5555

5656
Such cases can sometimes be resolved by iterating "by value" (or using
@@ -66,7 +66,7 @@ let mut b = || {
6666
yield x; // <-- Now yield is OK.
6767
}
6868
};
69-
Pin::new(&mut b).resume();
69+
Pin::new(&mut b).resume(());
7070
```
7171

7272
If taking ownership is not an option, using indices can work too:
@@ -83,7 +83,7 @@ let mut b = || {
8383
yield x; // <-- Now yield is OK.
8484
}
8585
};
86-
Pin::new(&mut b).resume();
86+
Pin::new(&mut b).resume(());
8787
8888
// (*) -- Unfortunately, these temporaries are currently required.
8989
// See <https://github.com/rust-lang/rust/issues/43122>.

src/librustc_mir/dataflow/impls/storage_liveness.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
3131
self.body.local_decls.len()
3232
}
3333

34-
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
35-
// Nothing is live on function entry (generators only have a self
36-
// argument, and we don't care about that)
37-
assert_eq!(1, self.body.arg_count);
34+
fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
35+
// The resume argument is live on function entry (we don't care about
36+
// the `self` argument)
37+
for arg in self.body.args_iter().skip(1) {
38+
on_entry.insert(arg);
39+
}
3840
}
3941

4042
fn statement_effect(&self, trans: &mut GenKillSet<Local>, loc: Location) {
@@ -100,10 +102,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
100102
self.body.local_decls.len()
101103
}
102104

103-
fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
104-
// Nothing is live on function entry (generators only have a self
105-
// argument, and we don't care about that)
106-
assert_eq!(1, self.body.arg_count);
105+
fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
106+
// The resume argument is live on function entry (we don't care about
107+
// the `self` argument)
108+
for arg in self.body.args_iter().skip(1) {
109+
on_entry.insert(arg);
110+
}
107111
}
108112

109113
fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {

src/librustc_mir/transform/generator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,7 @@ fn create_generator_drop_shim<'tcx>(
885885
drop_clean: BasicBlock,
886886
) -> BodyAndCache<'tcx> {
887887
let mut body = body.clone();
888+
body.arg_count = 1; // make sure the resume argument is not included here
888889

889890
let source_info = source_info(&body);
890891

@@ -1164,7 +1165,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
11641165

11651166
// Update our MIR struct to reflect the changed we've made
11661167
body.yield_ty = None;
1167-
body.arg_count = 1;
1168+
body.arg_count = 2; // self, resume arg
11681169
body.spread_arg = None;
11691170
body.generator_layout = Some(layout);
11701171

src/librustc_mir_build/build/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,16 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
7575
// HACK(eddyb) Avoid having RustCall on closures,
7676
// as it adds unnecessary (and wrong) auto-tupling.
7777
abi = Abi::Rust;
78-
Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
78+
vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
7979
}
8080
ty::Generator(..) => {
8181
let gen_ty = tcx.body_tables(body_id).node_type(id);
82-
Some(ArgInfo(gen_ty, None, None, None))
82+
vec![
83+
ArgInfo(gen_ty, None, None, None),
84+
ArgInfo(tcx.mk_unit(), None, None, None),
85+
]
8386
}
84-
_ => None,
87+
_ => vec![],
8588
};
8689

8790
let safety = match fn_sig.unsafety {

src/libstd/future.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
4040
// Safe because we're !Unpin + !Drop mapping to a ?Unpin value
4141
let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
4242
let _guard = unsafe { set_task_context(cx) };
43-
match gen.resume() {
43+
match gen.resume(
44+
#[cfg(not(bootstrap))]
45+
(),
46+
) {
4447
GeneratorState::Yielded(()) => Poll::Pending,
4548
GeneratorState::Complete(x) => Poll::Ready(x),
4649
}

src/test/debuginfo/generator-locals.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ fn main() {
7878
_zzz(); // #break
7979
a = c;
8080
};
81-
Pin::new(&mut b).resume();
82-
Pin::new(&mut b).resume();
83-
Pin::new(&mut b).resume();
81+
Pin::new(&mut b).resume(());
82+
Pin::new(&mut b).resume(());
83+
Pin::new(&mut b).resume(());
8484
_zzz(); // #break
8585
}
8686

src/test/debuginfo/generator-objects.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ fn main() {
5757
println!("{} {} {}", a, c, d);
5858
};
5959
_zzz(); // #break
60-
Pin::new(&mut b).resume();
60+
Pin::new(&mut b).resume(());
6161
_zzz(); // #break
62-
Pin::new(&mut b).resume();
62+
Pin::new(&mut b).resume(());
6363
_zzz(); // #break
64-
Pin::new(&mut b).resume();
64+
Pin::new(&mut b).resume(());
6565
_zzz(); // #break
6666
}
6767

src/test/debuginfo/issue-57822.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn main() {
4545
yield;
4646
};
4747
let mut b = move || {
48-
Pin::new(&mut a).resume();
48+
Pin::new(&mut a).resume(());
4949
yield;
5050
};
5151

src/test/run-fail/generator-resume-after-panic.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn main() {
1616
yield;
1717
};
1818
panic::catch_unwind(panic::AssertUnwindSafe(|| {
19-
let x = Pin::new(&mut g).resume();
19+
let x = Pin::new(&mut g).resume(());
2020
}));
21-
Pin::new(&mut g).resume();
21+
Pin::new(&mut g).resume(());
2222
}

0 commit comments

Comments
 (0)