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

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