mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 20:34:06 +00:00
Add a resume type parameter to Generator
This commit is contained in:
parent
0cbcb17d33
commit
044fe0f558
@ -37,11 +37,11 @@ fn main() {
|
||||
return "foo"
|
||||
};
|
||||
|
||||
match Pin::new(&mut generator).resume() {
|
||||
match Pin::new(&mut generator).resume(()) {
|
||||
GeneratorState::Yielded(1) => {}
|
||||
_ => panic!("unexpected value from resume"),
|
||||
}
|
||||
match Pin::new(&mut generator).resume() {
|
||||
match Pin::new(&mut generator).resume(()) {
|
||||
GeneratorState::Complete("foo") => {}
|
||||
_ => panic!("unexpected value from resume"),
|
||||
}
|
||||
@ -71,9 +71,9 @@ fn main() {
|
||||
};
|
||||
|
||||
println!("1");
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume(());
|
||||
println!("3");
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume(());
|
||||
println!("5");
|
||||
}
|
||||
```
|
||||
@ -92,10 +92,10 @@ The `Generator` trait in `std::ops` currently looks like:
|
||||
# use std::ops::GeneratorState;
|
||||
# use std::pin::Pin;
|
||||
|
||||
pub trait Generator {
|
||||
pub trait Generator<R = ()> {
|
||||
type Yield;
|
||||
type Return;
|
||||
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
}
|
||||
```
|
||||
|
||||
@ -152,10 +152,6 @@ closure-like semantics. Namely:
|
||||
* Whenever a generator is dropped it will drop all captured environment
|
||||
variables.
|
||||
|
||||
Note that unlike closures, generators at this time cannot take any arguments.
|
||||
That is, generators must always look like `|| { ... }`. This restriction may be
|
||||
lifted at a future date, the design is ongoing!
|
||||
|
||||
### Generators as state machines
|
||||
|
||||
In the compiler, generators are currently compiled as state machines. Each
|
||||
@ -179,8 +175,8 @@ fn main() {
|
||||
return ret
|
||||
};
|
||||
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume(());
|
||||
Pin::new(&mut generator).resume(());
|
||||
}
|
||||
```
|
||||
|
||||
@ -205,7 +201,7 @@ fn main() {
|
||||
type Yield = i32;
|
||||
type Return = &'static str;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<i32, &'static str> {
|
||||
fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
|
||||
use std::mem;
|
||||
match mem::replace(&mut *self, __Generator::Done) {
|
||||
__Generator::Start(s) => {
|
||||
@ -228,8 +224,8 @@ fn main() {
|
||||
__Generator::Start(ret)
|
||||
};
|
||||
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume(());
|
||||
Pin::new(&mut generator).resume(());
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1103,6 +1103,7 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<T: ?Sized> Unpin for Box<T> {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
|
||||
type Yield = G::Yield;
|
||||
@ -1113,6 +1114,7 @@ impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
|
||||
type Yield = G::Yield;
|
||||
@ -1123,6 +1125,28 @@ impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume(Pin::new(&mut *self), arg)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume((*self).as_mut(), arg)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<F: ?Sized + Future + Unpin> Future for Box<F> {
|
||||
type Output = F::Output;
|
||||
|
@ -50,11 +50,11 @@ pub enum GeneratorState<Y, R> {
|
||||
/// return "foo"
|
||||
/// };
|
||||
///
|
||||
/// match Pin::new(&mut generator).resume() {
|
||||
/// match Pin::new(&mut generator).resume(()) {
|
||||
/// GeneratorState::Yielded(1) => {}
|
||||
/// _ => panic!("unexpected return from resume"),
|
||||
/// }
|
||||
/// match Pin::new(&mut generator).resume() {
|
||||
/// match Pin::new(&mut generator).resume(()) {
|
||||
/// GeneratorState::Complete("foo") => {}
|
||||
/// _ => panic!("unexpected return from resume"),
|
||||
/// }
|
||||
@ -67,7 +67,7 @@ pub enum GeneratorState<Y, R> {
|
||||
#[lang = "generator"]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
#[fundamental]
|
||||
pub trait Generator {
|
||||
pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
|
||||
/// The type of value this generator yields.
|
||||
///
|
||||
/// This associated type corresponds to the `yield` expression and the
|
||||
@ -110,9 +110,13 @@ pub trait Generator {
|
||||
/// been returned previously. While generator literals in the language are
|
||||
/// guaranteed to panic on resuming after `Complete`, this is not guaranteed
|
||||
/// for all implementations of the `Generator` trait.
|
||||
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
fn resume(
|
||||
self: Pin<&mut Self>,
|
||||
#[cfg(not(bootstrap))] arg: R,
|
||||
) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
|
||||
type Yield = G::Yield;
|
||||
@ -123,6 +127,7 @@ impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
|
||||
type Yield = G::Yield;
|
||||
@ -132,3 +137,25 @@ impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
|
||||
G::resume(Pin::new(&mut *self))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume((*self).as_mut(), arg)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume(Pin::new(&mut *self), arg)
|
||||
}
|
||||
}
|
||||
|
@ -643,8 +643,10 @@ pub fn generator_trait_ref_and_outputs(
|
||||
self_ty: Ty<'tcx>,
|
||||
sig: ty::PolyGenSig<'tcx>,
|
||||
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
|
||||
let trait_ref =
|
||||
ty::TraitRef { def_id: fn_trait_def_id, substs: tcx.mk_substs_trait(self_ty, &[]) };
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: fn_trait_def_id,
|
||||
substs: tcx.mk_substs_trait(self_ty, &[tcx.mk_unit().into()]),
|
||||
};
|
||||
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
|
||||
}
|
||||
|
||||
|
@ -2350,8 +2350,8 @@ impl<'tcx> ty::Instance<'tcx> {
|
||||
]);
|
||||
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
|
||||
|
||||
tcx.mk_fn_sig(iter::once(env_ty),
|
||||
ret_ty,
|
||||
tcx.mk_fn_sig([env_ty, tcx.mk_unit()].iter(),
|
||||
&ret_ty,
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
rustc_target::spec::abi::Abi::Rust
|
||||
|
@ -12,7 +12,7 @@ let mut b = || {
|
||||
yield (); // ...is still in scope here, when the yield occurs.
|
||||
println!("{}", a);
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
```
|
||||
|
||||
At present, it is not permitted to have a yield that occurs while a
|
||||
@ -31,7 +31,7 @@ let mut b = || {
|
||||
yield ();
|
||||
println!("{}", a);
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
```
|
||||
|
||||
This is a very simple case, of course. In more complex cases, we may
|
||||
@ -50,7 +50,7 @@ let mut b = || {
|
||||
yield x; // ...when this yield occurs.
|
||||
}
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
```
|
||||
|
||||
Such cases can sometimes be resolved by iterating "by value" (or using
|
||||
@ -66,7 +66,7 @@ let mut b = || {
|
||||
yield x; // <-- Now yield is OK.
|
||||
}
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
```
|
||||
|
||||
If taking ownership is not an option, using indices can work too:
|
||||
@ -83,7 +83,7 @@ let mut b = || {
|
||||
yield x; // <-- Now yield is OK.
|
||||
}
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
|
||||
// (*) -- Unfortunately, these temporaries are currently required.
|
||||
// See <https://github.com/rust-lang/rust/issues/43122>.
|
||||
|
@ -31,10 +31,12 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
|
||||
self.body.local_decls.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
|
||||
// Nothing is live on function entry (generators only have a self
|
||||
// argument, and we don't care about that)
|
||||
assert_eq!(1, self.body.arg_count);
|
||||
fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
|
||||
// The resume argument is live on function entry (we don't care about
|
||||
// the `self` argument)
|
||||
for arg in self.body.args_iter().skip(1) {
|
||||
on_entry.insert(arg);
|
||||
}
|
||||
}
|
||||
|
||||
fn statement_effect(&self, trans: &mut GenKillSet<Local>, loc: Location) {
|
||||
@ -100,10 +102,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
|
||||
self.body.local_decls.len()
|
||||
}
|
||||
|
||||
fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
|
||||
// Nothing is live on function entry (generators only have a self
|
||||
// argument, and we don't care about that)
|
||||
assert_eq!(1, self.body.arg_count);
|
||||
fn start_block_effect(&self, on_entry: &mut BitSet<Local>) {
|
||||
// The resume argument is live on function entry (we don't care about
|
||||
// the `self` argument)
|
||||
for arg in self.body.args_iter().skip(1) {
|
||||
on_entry.insert(arg);
|
||||
}
|
||||
}
|
||||
|
||||
fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {
|
||||
|
@ -885,6 +885,7 @@ fn create_generator_drop_shim<'tcx>(
|
||||
drop_clean: BasicBlock,
|
||||
) -> BodyAndCache<'tcx> {
|
||||
let mut body = body.clone();
|
||||
body.arg_count = 1; // make sure the resume argument is not included here
|
||||
|
||||
let source_info = source_info(&body);
|
||||
|
||||
@ -1164,7 +1165,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||
|
||||
// Update our MIR struct to reflect the changed we've made
|
||||
body.yield_ty = None;
|
||||
body.arg_count = 1;
|
||||
body.arg_count = 2; // self, resume arg
|
||||
body.spread_arg = None;
|
||||
body.generator_layout = Some(layout);
|
||||
|
||||
|
@ -75,13 +75,16 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
|
||||
// HACK(eddyb) Avoid having RustCall on closures,
|
||||
// as it adds unnecessary (and wrong) auto-tupling.
|
||||
abi = Abi::Rust;
|
||||
Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
|
||||
vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
|
||||
}
|
||||
ty::Generator(..) => {
|
||||
let gen_ty = tcx.body_tables(body_id).node_type(id);
|
||||
Some(ArgInfo(gen_ty, None, None, None))
|
||||
vec![
|
||||
ArgInfo(gen_ty, None, None, None),
|
||||
ArgInfo(tcx.mk_unit(), None, None, None),
|
||||
]
|
||||
}
|
||||
_ => None,
|
||||
_ => vec![],
|
||||
};
|
||||
|
||||
let safety = match fn_sig.unsafety {
|
||||
|
@ -40,7 +40,10 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
|
||||
// Safe because we're !Unpin + !Drop mapping to a ?Unpin value
|
||||
let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
|
||||
let _guard = unsafe { set_task_context(cx) };
|
||||
match gen.resume() {
|
||||
match gen.resume(
|
||||
#[cfg(not(bootstrap))]
|
||||
(),
|
||||
) {
|
||||
GeneratorState::Yielded(()) => Poll::Pending,
|
||||
GeneratorState::Complete(x) => Poll::Ready(x),
|
||||
}
|
||||
|
@ -78,9 +78,9 @@ fn main() {
|
||||
_zzz(); // #break
|
||||
a = c;
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
Pin::new(&mut b).resume(());
|
||||
Pin::new(&mut b).resume(());
|
||||
_zzz(); // #break
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,11 @@ fn main() {
|
||||
println!("{} {} {}", a, c, d);
|
||||
};
|
||||
_zzz(); // #break
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
_zzz(); // #break
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
_zzz(); // #break
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
_zzz(); // #break
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ fn main() {
|
||||
yield;
|
||||
};
|
||||
let mut b = move || {
|
||||
Pin::new(&mut a).resume();
|
||||
Pin::new(&mut a).resume(());
|
||||
yield;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ fn main() {
|
||||
yield;
|
||||
};
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let x = Pin::new(&mut g).resume();
|
||||
let x = Pin::new(&mut g).resume(());
|
||||
}));
|
||||
Pin::new(&mut g).resume();
|
||||
Pin::new(&mut g).resume(());
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
||||
let mut g = || {
|
||||
yield;
|
||||
};
|
||||
Pin::new(&mut g).resume(); // Yields once.
|
||||
Pin::new(&mut g).resume(); // Completes here.
|
||||
Pin::new(&mut g).resume(); // Panics here.
|
||||
Pin::new(&mut g).resume(()); // Yields once.
|
||||
Pin::new(&mut g).resume(()); // Completes here.
|
||||
Pin::new(&mut g).resume(()); // Panics here.
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ fn generator(a: &Allocator, run_count: usize) {
|
||||
);
|
||||
};
|
||||
for _ in 0..run_count {
|
||||
Pin::new(&mut gen).resume();
|
||||
Pin::new(&mut gen).resume(());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ fn msg() -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn foo() -> impl Generator<Yield=(), Return=u32> {
|
||||
pub fn foo() -> impl Generator<(), Yield=(), Return=u32> {
|
||||
|| {
|
||||
yield;
|
||||
return msg();
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::marker::Unpin;
|
||||
use std::ops::Generator;
|
||||
|
||||
pub fn foo() -> impl Generator<Yield = (), Return = ()> {
|
||||
pub fn foo() -> impl Generator<(), Yield = (), Return = ()> {
|
||||
|| {
|
||||
if false {
|
||||
yield;
|
||||
@ -11,7 +11,7 @@ pub fn foo() -> impl Generator<Yield = (), Return = ()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bar<T: 'static>(t: T) -> Box<Generator<Yield = T, Return = ()> + Unpin> {
|
||||
pub fn bar<T: 'static>(t: T) -> Box<Generator<(), Yield = T, Return = ()> + Unpin> {
|
||||
Box::new(|| {
|
||||
yield t;
|
||||
})
|
||||
|
@ -6,7 +6,7 @@ use std::pin::Pin;
|
||||
fn main() {
|
||||
let _b = {
|
||||
let a = 3;
|
||||
Pin::new(&mut || yield &a).resume()
|
||||
Pin::new(&mut || yield &a).resume(())
|
||||
//~^ ERROR: `a` does not live long enough
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/borrowing.rs:9:33
|
||||
|
|
||||
LL | Pin::new(&mut || yield &a).resume()
|
||||
LL | Pin::new(&mut || yield &a).resume(())
|
||||
| ----------^
|
||||
| | |
|
||||
| | borrowed value does not live long enough
|
||||
|
@ -35,9 +35,9 @@ fn t1() {
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
Pin::new(&mut a).resume();
|
||||
Pin::new(&mut a).resume(());
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
Pin::new(&mut a).resume();
|
||||
Pin::new(&mut a).resume(());
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
}
|
||||
|
||||
@ -51,8 +51,8 @@ fn t2() {
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
Pin::new(&mut a).resume();
|
||||
Pin::new(&mut a).resume(());
|
||||
assert_eq!(A.load(Ordering::SeqCst), n);
|
||||
Pin::new(&mut a).resume();
|
||||
Pin::new(&mut a).resume(());
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
}
|
||||
|
@ -7,10 +7,10 @@ use std::ops::{GeneratorState, Generator};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
|
||||
where T: Generator<Yield = ()> + Unpin,
|
||||
where T: Generator<(), Yield = ()> + Unpin,
|
||||
{
|
||||
loop {
|
||||
match Pin::new(&mut t).resume() {
|
||||
match Pin::new(&mut t).resume(()) {
|
||||
GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
|
||||
GeneratorState::Complete(ret) => {
|
||||
assert_eq!(amt, 0);
|
||||
|
@ -37,7 +37,7 @@ fn main() {
|
||||
};
|
||||
|
||||
loop {
|
||||
match Pin::new(&mut a).resume() {
|
||||
match Pin::new(&mut a).resume(()) {
|
||||
GeneratorState::Complete(()) => break,
|
||||
_ => (),
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ fn t1() {
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
drop(Pin::new(&mut foo).resume());
|
||||
drop(Pin::new(&mut foo).resume(()));
|
||||
assert_eq!(A.load(Ordering::SeqCst), n);
|
||||
drop(foo);
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
@ -43,7 +43,7 @@ fn t2() {
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
drop(Pin::new(&mut foo).resume());
|
||||
drop(Pin::new(&mut foo).resume(()));
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
drop(foo);
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
|
@ -15,6 +15,6 @@ fn main() {
|
||||
let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
|
||||
yield;
|
||||
};
|
||||
Pin::new(&mut gen).resume();
|
||||
Pin::new(&mut gen).resume(());
|
||||
// drops the RefCell and then the Ref, leading to use-after-free
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||
x
|
||||
};
|
||||
loop {
|
||||
match Pin::new(&mut g).resume() {
|
||||
match Pin::new(&mut g).resume(()) {
|
||||
GeneratorState::Complete(c) => return c,
|
||||
//~^ ERROR explicit lifetime required
|
||||
GeneratorState::Yielded(_) => (),
|
||||
|
@ -2,14 +2,14 @@
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{ Generator, GeneratorState };
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn foo(_: &str) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
fn bar(baz: String) -> impl Generator<Yield = String, Return = ()> {
|
||||
fn bar(baz: String) -> impl Generator<(), Yield = String, Return = ()> {
|
||||
move || {
|
||||
yield foo(&baz);
|
||||
}
|
||||
@ -19,7 +19,7 @@ fn foo2(_: &str) -> Result<String, ()> {
|
||||
Err(())
|
||||
}
|
||||
|
||||
fn bar2(baz: String) -> impl Generator<Yield = String, Return = ()> {
|
||||
fn bar2(baz: String) -> impl Generator<(), Yield = String, Return = ()> {
|
||||
move || {
|
||||
if let Ok(quux) = foo2(&baz) {
|
||||
yield quux;
|
||||
@ -28,6 +28,9 @@ fn bar2(baz: String) -> impl Generator<Yield = String, Return = ()> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(Pin::new(&mut bar(String::new())).resume(), GeneratorState::Yielded(String::new()));
|
||||
assert_eq!(Pin::new(&mut bar2(String::new())).resume(), GeneratorState::Complete(()));
|
||||
assert_eq!(
|
||||
Pin::new(&mut bar(String::new())).resume(()),
|
||||
GeneratorState::Yielded(String::new())
|
||||
);
|
||||
assert_eq!(Pin::new(&mut bar2(String::new())).resume(()), GeneratorState::Complete(()));
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ fn drop_and_yield() {
|
||||
String::new();
|
||||
yield;
|
||||
};
|
||||
Box::pin(x).as_mut().resume();
|
||||
Box::pin(x).as_mut().resume(());
|
||||
let y = static || {
|
||||
String::new();
|
||||
yield;
|
||||
};
|
||||
Box::pin(y).as_mut().resume();
|
||||
Box::pin(y).as_mut().resume(());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -10,18 +10,18 @@ struct W<T>(T);
|
||||
|
||||
// This impl isn't safe in general, but the generator used in this test is movable
|
||||
// so it won't cause problems.
|
||||
impl<T: Generator<Return = ()> + Unpin> Iterator for W<T> {
|
||||
impl<T: Generator<(), Return = ()> + Unpin> Iterator for W<T> {
|
||||
type Item = T::Yield;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match Pin::new(&mut self.0).resume() {
|
||||
match Pin::new(&mut self.0).resume(()) {
|
||||
GeneratorState::Complete(..) => None,
|
||||
GeneratorState::Yielded(v) => Some(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test() -> impl Generator<Return=(), Yield=u8> + Unpin {
|
||||
fn test() -> impl Generator<(), Return=(), Yield=u8> + Unpin {
|
||||
|| {
|
||||
for i in 1..6 {
|
||||
yield i
|
||||
|
@ -10,5 +10,5 @@ fn main() {
|
||||
let mut a = || {
|
||||
b(yield);
|
||||
};
|
||||
Pin::new(&mut a).resume();
|
||||
Pin::new(&mut a).resume(());
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ fn main() {
|
||||
yield 2;
|
||||
};
|
||||
|
||||
match Pin::new(&mut sub_generator).resume() {
|
||||
match Pin::new(&mut sub_generator).resume(()) {
|
||||
GeneratorState::Yielded(x) => {
|
||||
yield x;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ fn main() {
|
||||
|
||||
assert_eq!(A.load(Ordering::SeqCst), 0);
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
Pin::new(&mut foo).resume()
|
||||
Pin::new(&mut foo).resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
@ -50,7 +50,7 @@ fn main() {
|
||||
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
Pin::new(&mut foo).resume()
|
||||
Pin::new(&mut foo).resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
|
@ -17,13 +17,13 @@ fn main() {
|
||||
};
|
||||
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
Pin::new(&mut foo).resume()
|
||||
Pin::new(&mut foo).resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
|
||||
for _ in 0..10 {
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
Pin::new(&mut foo).resume()
|
||||
Pin::new(&mut foo).resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
@ -16,12 +16,12 @@ fn main() {
|
||||
yield;
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
||||
match panic::catch_unwind(move || Pin::new(&mut foo).resume()) {
|
||||
match panic::catch_unwind(move || Pin::new(&mut foo).resume(())) {
|
||||
Ok(_) => panic!("generator successfully resumed"),
|
||||
Err(_) => {}
|
||||
}
|
||||
|
@ -9,6 +9,6 @@ fn main() {
|
||||
//~^ ERROR the size for values of type
|
||||
yield s[..];
|
||||
};
|
||||
Pin::new(&mut gen).resume();
|
||||
Pin::new(&mut gen).resume(());
|
||||
//~^ ERROR the size for values of type
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ LL | | };
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/sized-yield.rs:12:23
|
||||
|
|
||||
LL | Pin::new(&mut gen).resume();
|
||||
LL | Pin::new(&mut gen).resume(());
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `str`
|
||||
|
@ -17,7 +17,7 @@ fn simple() {
|
||||
}
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -33,7 +33,7 @@ fn return_capture() {
|
||||
a
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -45,11 +45,11 @@ fn simple_yield() {
|
||||
yield;
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -62,11 +62,11 @@ fn yield_capture() {
|
||||
yield b;
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -79,11 +79,11 @@ fn simple_yield_value() {
|
||||
return String::from("foo")
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(ref s) if *s == "bar" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -97,11 +97,11 @@ fn return_after_yield() {
|
||||
return a
|
||||
};
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -149,11 +149,11 @@ fn send_and_sync() {
|
||||
fn send_over_threads() {
|
||||
let mut foo = || { yield };
|
||||
thread::spawn(move || {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
@ -162,11 +162,11 @@ fn send_over_threads() {
|
||||
let a = String::from("a");
|
||||
let mut foo = || { yield a };
|
||||
thread::spawn(move || {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(ref s) if *s == "a" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -15,6 +15,6 @@ fn main() {
|
||||
// Safety: We shadow the original generator variable so have no safe API to
|
||||
// move it after this point.
|
||||
let mut generator = unsafe { Pin::new_unchecked(&mut generator) };
|
||||
assert_eq!(generator.as_mut().resume(), GeneratorState::Yielded(()));
|
||||
assert_eq!(generator.as_mut().resume(), GeneratorState::Complete(()));
|
||||
assert_eq!(generator.as_mut().resume(()), GeneratorState::Yielded(()));
|
||||
assert_eq!(generator.as_mut().resume(()), GeneratorState::Complete(()));
|
||||
}
|
||||
|
@ -10,5 +10,5 @@ use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
Pin::new(&mut foo::foo()).resume();
|
||||
Pin::new(&mut foo::foo()).resume(());
|
||||
}
|
||||
|
@ -12,18 +12,18 @@ use std::pin::Pin;
|
||||
fn main() {
|
||||
let mut foo = xcrate::foo();
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
||||
let mut foo = xcrate::bar(3);
|
||||
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Yielded(3) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match Pin::new(&mut foo).resume() {
|
||||
match Pin::new(&mut foo).resume(()) {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ fn yield_during_iter_borrowed_slice_3() {
|
||||
yield p;
|
||||
}
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn yield_during_iter_borrowed_slice_4() {
|
||||
@ -56,7 +56,7 @@ fn yield_during_iter_borrowed_slice_4() {
|
||||
}
|
||||
};
|
||||
println!("{}", x[0]); //~ ERROR
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn yield_during_range_iter() {
|
||||
@ -69,7 +69,7 @@ fn yield_during_range_iter() {
|
||||
yield x;
|
||||
}
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -16,7 +16,7 @@ LL | for p in &mut x {
|
||||
...
|
||||
LL | println!("{}", x[0]);
|
||||
| ^ immutable borrow occurs here
|
||||
LL | Pin::new(&mut b).resume();
|
||||
LL | Pin::new(&mut b).resume(());
|
||||
| ------ mutable borrow later used here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -15,7 +15,7 @@ fn borrow_local_inline() {
|
||||
yield();
|
||||
println!("{}", a);
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn borrow_local_inline_done() {
|
||||
@ -26,7 +26,7 @@ fn borrow_local_inline_done() {
|
||||
}
|
||||
yield();
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn borrow_local() {
|
||||
@ -43,7 +43,7 @@ fn borrow_local() {
|
||||
println!("{}", b);
|
||||
}
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -12,7 +12,7 @@ fn reborrow_shared_ref(x: &i32) {
|
||||
yield();
|
||||
println!("{}", a);
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn reborrow_mutable_ref(x: &mut i32) {
|
||||
@ -23,7 +23,7 @@ fn reborrow_mutable_ref(x: &mut i32) {
|
||||
yield();
|
||||
println!("{}", a);
|
||||
};
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn reborrow_mutable_ref_2(x: &mut i32) {
|
||||
@ -34,7 +34,7 @@ fn reborrow_mutable_ref_2(x: &mut i32) {
|
||||
println!("{}", a);
|
||||
};
|
||||
println!("{}", x); //~ ERROR
|
||||
Pin::new(&mut b).resume();
|
||||
Pin::new(&mut b).resume(());
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -8,7 +8,7 @@ LL | let a = &mut *x;
|
||||
...
|
||||
LL | println!("{}", x);
|
||||
| ^ second borrow occurs here
|
||||
LL | Pin::new(&mut b).resume();
|
||||
LL | Pin::new(&mut b).resume(());
|
||||
| ------ first borrow later used here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -15,7 +15,7 @@ where
|
||||
type Item = G::Yield;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match Pin::new(&mut self.0).resume() {
|
||||
match Pin::new(&mut self.0).resume(()) {
|
||||
Yielded(y) => Some(y),
|
||||
_ => None
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user