Add a resume type parameter to `Generator`

This commit is contained in:
Jonas Schievink 2020-01-25 20:03:10 +01:00
parent 0cbcb17d33
commit 044fe0f558
46 changed files with 185 additions and 122 deletions

View File

@ -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(());
}
```

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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),
}

View File

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

View File

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

View File

@ -45,7 +45,7 @@ fn main() {
yield;
};
let mut b = move || {
Pin::new(&mut a).resume();
Pin::new(&mut a).resume(());
yield;
};

View File

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

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,7 +37,7 @@ fn main() {
};
loop {
match Pin::new(&mut a).resume() {
match Pin::new(&mut a).resume(()) {
GeneratorState::Complete(()) => break,
_ => (),
}

View File

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

View File

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

View File

@ -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(_) => (),

View File

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

View File

@ -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() {

View File

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

View File

@ -10,5 +10,5 @@ fn main() {
let mut a = || {
b(yield);
};
Pin::new(&mut a).resume();
Pin::new(&mut a).resume(());
}

View File

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

View File

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

View File

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

View File

@ -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(_) => {}
}

View File

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

View File

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

View File

@ -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),
}

View File

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

View File

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

View File

@ -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),
}

View File

@ -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() { }

View File

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

View File

@ -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() { }

View File

@ -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() { }

View File

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

View File

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