Change generator trait to use pinning
This commit is contained in:
parent
8611577360
commit
a3fdee9a75
44 changed files with 209 additions and 170 deletions
|
@ -29,6 +29,7 @@ A syntactical example of a generator is:
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut generator = || {
|
||||
|
@ -36,11 +37,11 @@ fn main() {
|
|||
return "foo"
|
||||
};
|
||||
|
||||
match unsafe { generator.resume() } {
|
||||
match Pin::new(&mut generator).resume() {
|
||||
GeneratorState::Yielded(1) => {}
|
||||
_ => panic!("unexpected value from resume"),
|
||||
}
|
||||
match unsafe { generator.resume() } {
|
||||
match Pin::new(&mut generator).resume() {
|
||||
GeneratorState::Complete("foo") => {}
|
||||
_ => panic!("unexpected value from resume"),
|
||||
}
|
||||
|
@ -60,6 +61,7 @@ prints all numbers in order:
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut generator = || {
|
||||
|
@ -69,9 +71,9 @@ fn main() {
|
|||
};
|
||||
|
||||
println!("1");
|
||||
unsafe { generator.resume() };
|
||||
Pin::new(&mut generator).resume();
|
||||
println!("3");
|
||||
unsafe { generator.resume() };
|
||||
Pin::new(&mut generator).resume();
|
||||
println!("5");
|
||||
}
|
||||
```
|
||||
|
@ -86,13 +88,14 @@ Feedback on the design and usage is always appreciated!
|
|||
The `Generator` trait in `std::ops` currently looks like:
|
||||
|
||||
```
|
||||
# #![feature(generator_trait)]
|
||||
# #![feature(arbitrary_self_types, generator_trait)]
|
||||
# use std::ops::GeneratorState;
|
||||
# use std::pin::Pin;
|
||||
|
||||
pub trait Generator {
|
||||
type Yield;
|
||||
type Return;
|
||||
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -167,6 +170,7 @@ Let's take a look at an example to see what's going on here:
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let ret = "foo";
|
||||
|
@ -175,17 +179,18 @@ fn main() {
|
|||
return ret
|
||||
};
|
||||
|
||||
unsafe { generator.resume() };
|
||||
unsafe { generator.resume() };
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume();
|
||||
}
|
||||
```
|
||||
|
||||
This generator literal will compile down to something similar to:
|
||||
|
||||
```rust
|
||||
#![feature(generators, generator_trait)]
|
||||
#![feature(arbitrary_self_types, generators, generator_trait)]
|
||||
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let ret = "foo";
|
||||
|
@ -200,9 +205,9 @@ fn main() {
|
|||
type Yield = i32;
|
||||
type Return = &'static str;
|
||||
|
||||
unsafe fn resume(&mut self) -> GeneratorState<i32, &'static str> {
|
||||
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<i32, &'static str> {
|
||||
use std::mem;
|
||||
match mem::replace(self, __Generator::Done) {
|
||||
match mem::replace(&mut *self, __Generator::Done) {
|
||||
__Generator::Start(s) => {
|
||||
*self = __Generator::Yield1(s);
|
||||
GeneratorState::Yielded(1)
|
||||
|
@ -223,8 +228,8 @@ fn main() {
|
|||
__Generator::Start(ret)
|
||||
};
|
||||
|
||||
unsafe { generator.resume() };
|
||||
unsafe { generator.resume() };
|
||||
Pin::new(&mut generator).resume();
|
||||
Pin::new(&mut generator).resume();
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -873,13 +873,12 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
|
|||
impl<T: ?Sized> Unpin for Box<T> { }
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<T> Generator for Box<T>
|
||||
where T: Generator + ?Sized
|
||||
{
|
||||
type Yield = T::Yield;
|
||||
type Return = T::Return;
|
||||
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
(**self).resume()
|
||||
impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume(Pin::new(&mut *self))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use crate::marker::Unpin;
|
||||
use crate::pin::Pin;
|
||||
|
||||
/// The result of a generator resumption.
|
||||
///
|
||||
/// This enum is returned from the `Generator::resume` method and indicates the
|
||||
|
@ -39,6 +42,7 @@ pub enum GeneratorState<Y, R> {
|
|||
/// #![feature(generators, generator_trait)]
|
||||
///
|
||||
/// use std::ops::{Generator, GeneratorState};
|
||||
/// use std::pin::Pin;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut generator = || {
|
||||
|
@ -46,11 +50,11 @@ pub enum GeneratorState<Y, R> {
|
|||
/// return "foo"
|
||||
/// };
|
||||
///
|
||||
/// match unsafe { generator.resume() } {
|
||||
/// match Pin::new(&mut generator).resume() {
|
||||
/// GeneratorState::Yielded(1) => {}
|
||||
/// _ => panic!("unexpected return from resume"),
|
||||
/// }
|
||||
/// match unsafe { generator.resume() } {
|
||||
/// match Pin::new(&mut generator).resume() {
|
||||
/// GeneratorState::Complete("foo") => {}
|
||||
/// _ => panic!("unexpected return from resume"),
|
||||
/// }
|
||||
|
@ -88,10 +92,6 @@ pub trait Generator {
|
|||
/// generator will continue executing until it either yields or returns, at
|
||||
/// which point this function will return.
|
||||
///
|
||||
/// The function is unsafe because it can be used on an immovable generator.
|
||||
/// After such a call, the immovable generator must not move again, but
|
||||
/// this is not enforced by the compiler.
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// The `GeneratorState` enum returned from this function indicates what
|
||||
|
@ -110,16 +110,25 @@ 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.
|
||||
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
|
||||
}
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<T> Generator for &mut T
|
||||
where T: Generator + ?Sized
|
||||
{
|
||||
type Yield = T::Yield;
|
||||
type Return = T::Return;
|
||||
unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
(**self).resume()
|
||||
impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume((*self).as_mut())
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
|
||||
type Yield = G::Yield;
|
||||
type Return = G::Return;
|
||||
|
||||
fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
G::resume(Pin::new(&mut *self))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2119,14 +2119,15 @@ This error occurs because a borrow in a generator persists across a
|
|||
yield point.
|
||||
|
||||
```compile_fail,E0626
|
||||
# #![feature(generators, generator_trait)]
|
||||
# #![feature(generators, generator_trait, pin)]
|
||||
# use std::ops::Generator;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let a = &String::new(); // <-- This borrow...
|
||||
yield (); // ...is still in scope here, when the yield occurs.
|
||||
println!("{}", a);
|
||||
};
|
||||
unsafe { b.resume() };
|
||||
Pin::new(&mut b).resume();
|
||||
```
|
||||
|
||||
At present, it is not permitted to have a yield that occurs while a
|
||||
|
@ -2137,14 +2138,15 @@ resolve the previous example by removing the borrow and just storing
|
|||
the integer by value:
|
||||
|
||||
```
|
||||
# #![feature(generators, generator_trait)]
|
||||
# #![feature(generators, generator_trait, pin)]
|
||||
# use std::ops::Generator;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let a = 3;
|
||||
yield ();
|
||||
println!("{}", a);
|
||||
};
|
||||
unsafe { b.resume() };
|
||||
Pin::new(&mut b).resume();
|
||||
```
|
||||
|
||||
This is a very simple case, of course. In more complex cases, we may
|
||||
|
@ -2154,37 +2156,40 @@ in those cases, something like the `Rc` or `Arc` types may be useful.
|
|||
This error also frequently arises with iteration:
|
||||
|
||||
```compile_fail,E0626
|
||||
# #![feature(generators, generator_trait)]
|
||||
# #![feature(generators, generator_trait, pin)]
|
||||
# use std::ops::Generator;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let v = vec![1,2,3];
|
||||
for &x in &v { // <-- borrow of `v` is still in scope...
|
||||
yield x; // ...when this yield occurs.
|
||||
}
|
||||
};
|
||||
unsafe { b.resume() };
|
||||
Pin::new(&mut b).resume();
|
||||
```
|
||||
|
||||
Such cases can sometimes be resolved by iterating "by value" (or using
|
||||
`into_iter()`) to avoid borrowing:
|
||||
|
||||
```
|
||||
# #![feature(generators, generator_trait)]
|
||||
# #![feature(generators, generator_trait, pin)]
|
||||
# use std::ops::Generator;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let v = vec![1,2,3];
|
||||
for x in v { // <-- Take ownership of the values instead!
|
||||
yield x; // <-- Now yield is OK.
|
||||
}
|
||||
};
|
||||
unsafe { b.resume() };
|
||||
Pin::new(&mut b).resume();
|
||||
```
|
||||
|
||||
If taking ownership is not an option, using indices can work too:
|
||||
|
||||
```
|
||||
# #![feature(generators, generator_trait)]
|
||||
# #![feature(generators, generator_trait, pin)]
|
||||
# use std::ops::Generator;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let v = vec![1,2,3];
|
||||
let len = v.len(); // (*)
|
||||
|
@ -2193,7 +2198,7 @@ let mut b = || {
|
|||
yield x; // <-- Now yield is OK.
|
||||
}
|
||||
};
|
||||
unsafe { b.resume() };
|
||||
Pin::new(&mut b).resume();
|
||||
|
||||
// (*) -- Unfortunately, these temporaries are currently required.
|
||||
// See <https://github.com/rust-lang/rust/issues/43122>.
|
||||
|
|
|
@ -33,7 +33,9 @@ impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
|
|||
impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
|
||||
type Output = T::Return;
|
||||
fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
|
||||
set_task_waker(lw, || match unsafe { Pin::get_unchecked_mut(self).0.resume() } {
|
||||
// Safe because we're !Unpin + !Drop mapping to a ?Unpin value
|
||||
let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
|
||||
set_task_waker(lw, || match gen.resume() {
|
||||
GeneratorState::Yielded(()) => Poll::Pending,
|
||||
GeneratorState::Complete(x) => Poll::Ready(x),
|
||||
})
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::ops::Generator;
|
||||
use std::panic;
|
||||
use std::pin::Pin;
|
||||
use std::usize;
|
||||
|
||||
struct InjectedFailure;
|
||||
|
@ -172,7 +173,7 @@ fn generator(a: &Allocator, run_count: usize) {
|
|||
);
|
||||
};
|
||||
for _ in 0..run_count {
|
||||
unsafe { gen.resume(); }
|
||||
Pin::new(&mut gen).resume();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::marker::Unpin;
|
||||
use std::ops::Generator;
|
||||
|
||||
pub fn foo() -> impl Generator<Yield = (), Return = ()> {
|
||||
|
@ -10,7 +11,7 @@ pub fn foo() -> impl Generator<Yield = (), Return = ()> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn bar<T: 'static>(t: T) -> Box<Generator<Yield = T, Return = ()>> {
|
||||
pub fn bar<T: Unpin + 'static>(t: T) -> Box<Generator<Yield = T, Return = ()> + Unpin> {
|
||||
Box::new(|| {
|
||||
yield t;
|
||||
})
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static A: AtomicUsize = AtomicUsize::new(0);
|
||||
|
@ -34,9 +35,9 @@ fn t1() {
|
|||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
unsafe { a.resume() };
|
||||
Pin::new(&mut a).resume();
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
unsafe { a.resume() };
|
||||
Pin::new(&mut a).resume();
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
}
|
||||
|
||||
|
@ -50,8 +51,8 @@ fn t2() {
|
|||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
unsafe { a.resume() };
|
||||
Pin::new(&mut a).resume();
|
||||
assert_eq!(A.load(Ordering::SeqCst), n);
|
||||
unsafe { a.resume() };
|
||||
Pin::new(&mut a).resume();
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::marker::Unpin;
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
|
||||
where T: Generator<Yield = ()>
|
||||
where T: Generator<Yield = ()> + Unpin,
|
||||
{
|
||||
loop {
|
||||
match unsafe { t.resume() } {
|
||||
match Pin::new(&mut t).resume() {
|
||||
GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
|
||||
GeneratorState::Complete(ret) => {
|
||||
assert_eq!(amt, 0);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static A: AtomicUsize = AtomicUsize::new(0);
|
||||
|
@ -29,7 +30,7 @@ fn t1() {
|
|||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
drop(unsafe { 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);
|
||||
|
@ -42,7 +43,7 @@ fn t2() {
|
|||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
drop(unsafe { 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);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{ Generator, GeneratorState };
|
||||
use std::pin::Pin;
|
||||
|
||||
fn foo(_: &str) -> String {
|
||||
String::new()
|
||||
|
@ -27,8 +28,6 @@ fn bar2(baz: String) -> impl Generator<Yield = String, Return = ()> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
|
||||
assert_eq!(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(()));
|
||||
}
|
||||
|
|
|
@ -2,24 +2,26 @@
|
|||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::marker::Unpin;
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::pin::Pin;
|
||||
|
||||
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 = ()>> 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 unsafe { 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> {
|
||||
fn test() -> impl Generator<Return=(), Yield=u8> + Unpin {
|
||||
|| {
|
||||
for i in 1..6 {
|
||||
yield i
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let b = |_| 3;
|
||||
let mut a = || {
|
||||
b(yield);
|
||||
};
|
||||
unsafe { a.resume() };
|
||||
Pin::new(&mut a).resume();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(generators)]
|
||||
#![feature(generator_trait)]
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::ops::GeneratorState;
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let _generator = || {
|
||||
|
@ -12,7 +11,7 @@ fn main() {
|
|||
yield 2;
|
||||
};
|
||||
|
||||
match unsafe { sub_generator.resume() } {
|
||||
match Pin::new(&mut sub_generator).resume() {
|
||||
GeneratorState::Yielded(x) => {
|
||||
yield x;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use std::ops::Generator;
|
||||
use std::panic;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static A: AtomicUsize = AtomicUsize::new(0);
|
||||
|
@ -34,7 +35,7 @@ fn main() {
|
|||
|
||||
assert_eq!(A.load(Ordering::SeqCst), 0);
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
unsafe { foo.resume() }
|
||||
Pin::new(&mut foo).resume()
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
|
@ -49,7 +50,7 @@ fn main() {
|
|||
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
unsafe { foo.resume() }
|
||||
Pin::new(&mut foo).resume()
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
use std::panic;
|
||||
|
||||
fn main() {
|
||||
|
@ -16,13 +17,13 @@ fn main() {
|
|||
};
|
||||
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
unsafe { foo.resume() }
|
||||
Pin::new(&mut foo).resume()
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
|
||||
for _ in 0..10 {
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
unsafe { foo.resume() }
|
||||
Pin::new(&mut foo).resume()
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::pin::Pin;
|
||||
use std::panic;
|
||||
|
||||
fn main() {
|
||||
|
@ -15,12 +16,12 @@ fn main() {
|
|||
yield;
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
||||
match panic::catch_unwind(move || unsafe { foo.resume() }) {
|
||||
match panic::catch_unwind(move || Pin::new(&mut foo).resume()) {
|
||||
Ok(_) => panic!("generator successfully resumed"),
|
||||
Err(_) => {}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::pin::Pin;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
|
@ -16,7 +17,7 @@ fn simple() {
|
|||
}
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -32,7 +33,7 @@ fn return_capture() {
|
|||
a
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -44,11 +45,11 @@ fn simple_yield() {
|
|||
yield;
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -61,11 +62,11 @@ fn yield_capture() {
|
|||
yield b;
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -78,11 +79,11 @@ fn simple_yield_value() {
|
|||
return String::from("foo")
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(ref s) if *s == "bar" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -96,11 +97,11 @@ fn return_after_yield() {
|
|||
return a
|
||||
};
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -148,11 +149,11 @@ fn send_and_sync() {
|
|||
fn send_over_threads() {
|
||||
let mut foo = || { yield };
|
||||
thread::spawn(move || {
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
@ -161,11 +162,11 @@ fn send_over_threads() {
|
|||
let a = String::from("a");
|
||||
let mut foo = || { yield a };
|
||||
thread::spawn(move || {
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(ref s) if *s == "a" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
|
||||
fn main() {
|
||||
|
@ -11,8 +12,9 @@ fn main() {
|
|||
yield;
|
||||
assert_eq!(b as *const _, &a as *const _);
|
||||
};
|
||||
unsafe {
|
||||
assert_eq!(generator.resume(), GeneratorState::Yielded(()));
|
||||
assert_eq!(generator.resume(), GeneratorState::Complete(()));
|
||||
}
|
||||
// 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(()));
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
extern crate xcrate_reachable as foo;
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
unsafe { foo::foo().resume(); }
|
||||
Pin::new(&mut foo::foo()).resume();
|
||||
}
|
||||
|
|
|
@ -7,22 +7,23 @@
|
|||
extern crate xcrate;
|
||||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut foo = xcrate::foo();
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
||||
let mut foo = xcrate::bar(3);
|
||||
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Yielded(3) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match unsafe { foo.resume() } {
|
||||
match Pin::new(&mut foo).resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/borrowing.rs:8:29
|
||||
--> $DIR/borrowing.rs:9:33
|
||||
|
|
||||
LL | unsafe { (|| yield &a).resume() }
|
||||
| -----------^-
|
||||
| || |
|
||||
| || borrowed value does not live long enough
|
||||
| |value captured here by generator
|
||||
| a temporary with access to the borrow is created here ...
|
||||
LL | Pin::new(&mut || yield &a).resume()
|
||||
| ----------^
|
||||
| | |
|
||||
| | borrowed value does not live long enough
|
||||
| value captured here by generator
|
||||
| a temporary with access to the borrow is created here ...
|
||||
LL | //~^ ERROR: `a` does not live long enough
|
||||
LL | };
|
||||
| -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
|
||||
|
@ -16,7 +16,7 @@ LL | };
|
|||
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
|
||||
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/borrowing.rs:15:20
|
||||
--> $DIR/borrowing.rs:16:20
|
||||
|
|
||||
LL | let _b = {
|
||||
| -- borrow later stored here
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let _b = {
|
||||
let a = 3;
|
||||
unsafe { (|| yield &a).resume() }
|
||||
Pin::new(&mut || yield &a).resume()
|
||||
//~^ ERROR: `a` does not live long enough
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/borrowing.rs:8:29
|
||||
--> $DIR/borrowing.rs:9:33
|
||||
|
|
||||
LL | unsafe { (|| yield &a).resume() }
|
||||
| -- ^ borrowed value does not live long enough
|
||||
| |
|
||||
| capture occurs here
|
||||
LL | Pin::new(&mut || yield &a).resume()
|
||||
| -- ^ borrowed value does not live long enough
|
||||
| |
|
||||
| capture occurs here
|
||||
LL | //~^ ERROR: `a` does not live long enough
|
||||
LL | };
|
||||
| - borrowed value only lives until here
|
||||
|
@ -13,7 +13,7 @@ LL | }
|
|||
| - borrowed value needs to live until here
|
||||
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/borrowing.rs:15:20
|
||||
--> $DIR/borrowing.rs:16:20
|
||||
|
|
||||
LL | || {
|
||||
| -- capture occurs here
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0597]: `*cell` does not live long enough
|
||||
--> $DIR/dropck.rs:9:40
|
||||
--> $DIR/dropck.rs:10:40
|
||||
|
|
||||
LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
|
||||
| ^^^^ borrowed value does not live long enough
|
||||
|
@ -13,7 +13,7 @@ LL | }
|
|||
= note: values in a scope are dropped in the opposite order they are defined
|
||||
|
||||
error[E0597]: `ref_` does not live long enough
|
||||
--> $DIR/dropck.rs:14:18
|
||||
--> $DIR/dropck.rs:15:18
|
||||
|
|
||||
LL | gen = || {
|
||||
| -- value captured here by generator
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let (mut gen, cell);
|
||||
|
@ -14,6 +15,6 @@ fn main() {
|
|||
let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
|
||||
yield;
|
||||
};
|
||||
unsafe { gen.resume(); }
|
||||
Pin::new(&mut gen).resume();
|
||||
// drops the RefCell and then the Ref, leading to use-after-free
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0597]: `*cell` does not live long enough
|
||||
--> $DIR/dropck.rs:9:40
|
||||
--> $DIR/dropck.rs:10:40
|
||||
|
|
||||
LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
|
||||
| ^^^^ borrowed value does not live long enough
|
||||
|
@ -10,7 +10,7 @@ LL | }
|
|||
= note: values in a scope are dropped in the opposite order they are created
|
||||
|
||||
error[E0597]: `ref_` does not live long enough
|
||||
--> $DIR/dropck.rs:14:18
|
||||
--> $DIR/dropck.rs:15:18
|
||||
|
|
||||
LL | gen = || {
|
||||
| -- capture occurs here
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/generator-region-requirements.rs:15:51
|
||||
--> $DIR/generator-region-requirements.rs:16:51
|
||||
|
|
||||
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||
| -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/generator-region-requirements.rs:15:51
|
||||
--> $DIR/generator-region-requirements.rs:16:51
|
||||
|
|
||||
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||
| -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
#![cfg_attr(nll, feature(nll))]
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||
let mut g = || {
|
||||
|
@ -11,7 +12,7 @@ fn dangle(x: &mut i32) -> &'static mut i32 {
|
|||
x
|
||||
};
|
||||
loop {
|
||||
match unsafe { g.resume() } {
|
||||
match Pin::new(&mut g).resume() {
|
||||
GeneratorState::Complete(c) => return c,
|
||||
//[nll]~^ ERROR explicit lifetime required
|
||||
//[ast]~^^ ERROR explicit lifetime required
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0521]: borrowed data escapes outside of generator
|
||||
--> $DIR/ref-escapes-but-not-over-yield.rs:14:9
|
||||
--> $DIR/ref-escapes-but-not-over-yield.rs:11:9
|
||||
|
|
||||
LL | let mut a = &3;
|
||||
| ----- `a` is declared here, outside of the generator body
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::cell::Cell;
|
||||
#![feature(generators)]
|
||||
|
||||
fn foo(x: &i32) {
|
||||
// In this case, a reference to `b` escapes the generator, but not
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0597]: `b` does not live long enough
|
||||
--> $DIR/ref-escapes-but-not-over-yield.rs:14:14
|
||||
--> $DIR/ref-escapes-but-not-over-yield.rs:11:14
|
||||
|
|
||||
LL | a = &b;
|
||||
| ^ borrowed value does not live long enough
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let s = String::from("foo");
|
||||
|
@ -8,6 +9,6 @@ fn main() {
|
|||
//~^ ERROR the size for values of type
|
||||
yield s[..];
|
||||
};
|
||||
unsafe { gen.resume(); }
|
||||
Pin::new(&mut gen).resume();
|
||||
//~^ ERROR the size for values of type
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/sized-yield.rs:7:26
|
||||
--> $DIR/sized-yield.rs:8:26
|
||||
|
|
||||
LL | let mut gen = move || {
|
||||
| __________________________^
|
||||
|
@ -13,10 +13,10 @@ LL | | };
|
|||
= note: the yield type of a generator must have a statically known size
|
||||
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/sized-yield.rs:11:17
|
||||
--> $DIR/sized-yield.rs:12:23
|
||||
|
|
||||
LL | unsafe { gen.resume(); }
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
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`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0626]: borrow may still be in use when generator yields
|
||||
--> $DIR/yield-while-iterating.rs:12:18
|
||||
--> $DIR/yield-while-iterating.rs:13:18
|
||||
|
|
||||
LL | for p in &x { //~ ERROR
|
||||
| ^^
|
||||
|
@ -7,7 +7,7 @@ LL | yield();
|
|||
| ------- possible yield occurs here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/yield-while-iterating.rs:57:20
|
||||
--> $DIR/yield-while-iterating.rs:58:20
|
||||
|
|
||||
LL | let mut b = || {
|
||||
| -- mutable borrow occurs here
|
||||
|
@ -16,8 +16,8 @@ LL | for p in &mut x {
|
|||
...
|
||||
LL | println!("{}", x[0]); //~ ERROR
|
||||
| ^ immutable borrow occurs here
|
||||
LL | b.resume();
|
||||
| - mutable borrow later used here
|
||||
LL | Pin::new(&mut b).resume();
|
||||
| ------ mutable borrow later used here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::cell::Cell;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn yield_during_iter_owned_data(x: Vec<i32>) {
|
||||
// The generator owns `x`, so we error out when yielding with a
|
||||
|
@ -33,7 +34,7 @@ fn yield_during_iter_borrowed_slice_2() {
|
|||
println!("{:?}", x);
|
||||
}
|
||||
|
||||
unsafe fn yield_during_iter_borrowed_slice_3() {
|
||||
fn yield_during_iter_borrowed_slice_3() {
|
||||
// OK to take a mutable ref to `x` and yield
|
||||
// up pointers from it:
|
||||
let mut x = vec![22_i32];
|
||||
|
@ -42,10 +43,10 @@ unsafe fn yield_during_iter_borrowed_slice_3() {
|
|||
yield p;
|
||||
}
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
unsafe fn yield_during_iter_borrowed_slice_4() {
|
||||
fn yield_during_iter_borrowed_slice_4() {
|
||||
// ...but not OK to do that while reading
|
||||
// from `x` too
|
||||
let mut x = vec![22_i32];
|
||||
|
@ -55,10 +56,10 @@ unsafe fn yield_during_iter_borrowed_slice_4() {
|
|||
}
|
||||
};
|
||||
println!("{}", x[0]); //~ ERROR
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
unsafe fn yield_during_range_iter() {
|
||||
fn yield_during_range_iter() {
|
||||
// Should be OK.
|
||||
let mut b = || {
|
||||
let v = vec![1,2,3];
|
||||
|
@ -68,7 +69,7 @@ unsafe fn yield_during_range_iter() {
|
|||
yield x;
|
||||
}
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0626]: borrow may still be in use when generator yields
|
||||
--> $DIR/yield-while-iterating.rs:12:19
|
||||
--> $DIR/yield-while-iterating.rs:13:19
|
||||
|
|
||||
LL | for p in &x { //~ ERROR
|
||||
| ^
|
||||
|
@ -7,7 +7,7 @@ LL | yield();
|
|||
| ------- possible yield occurs here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/yield-while-iterating.rs:57:20
|
||||
--> $DIR/yield-while-iterating.rs:58:20
|
||||
|
|
||||
LL | let mut b = || {
|
||||
| -- mutable borrow occurs here
|
||||
|
@ -16,7 +16,7 @@ LL | for p in &mut x {
|
|||
...
|
||||
LL | println!("{}", x[0]); //~ ERROR
|
||||
| ^ immutable borrow occurs here
|
||||
LL | b.resume();
|
||||
LL | Pin::new(&mut b).resume();
|
||||
LL | }
|
||||
| - mutable borrow ends here
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::cell::Cell;
|
||||
use std::pin::Pin;
|
||||
|
||||
unsafe fn borrow_local_inline() {
|
||||
fn borrow_local_inline() {
|
||||
// Not OK to yield with a borrow of a temporary.
|
||||
//
|
||||
// (This error occurs because the region shows up in the type of
|
||||
|
@ -17,10 +18,10 @@ unsafe fn borrow_local_inline() {
|
|||
yield();
|
||||
println!("{}", a);
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
unsafe fn borrow_local_inline_done() {
|
||||
fn borrow_local_inline_done() {
|
||||
// No error here -- `a` is not in scope at the point of `yield`.
|
||||
let mut b = move || {
|
||||
{
|
||||
|
@ -28,10 +29,10 @@ unsafe fn borrow_local_inline_done() {
|
|||
}
|
||||
yield();
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
unsafe fn borrow_local() {
|
||||
fn borrow_local() {
|
||||
// Not OK to yield with a borrow of a temporary.
|
||||
//
|
||||
// (This error occurs because the region shows up in the type of
|
||||
|
@ -46,7 +47,7 @@ unsafe fn borrow_local() {
|
|||
println!("{}", b);
|
||||
}
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0626]: borrow may still be in use when generator yields (Ast)
|
||||
--> $DIR/yield-while-local-borrowed.rs:14:22
|
||||
--> $DIR/yield-while-local-borrowed.rs:15:22
|
||||
|
|
||||
LL | let a = &mut 3;
|
||||
| ^
|
||||
|
@ -8,7 +8,7 @@ LL | yield();
|
|||
| ------- possible yield occurs here
|
||||
|
||||
error[E0626]: borrow may still be in use when generator yields (Ast)
|
||||
--> $DIR/yield-while-local-borrowed.rs:42:22
|
||||
--> $DIR/yield-while-local-borrowed.rs:43:22
|
||||
|
|
||||
LL | let b = &a;
|
||||
| ^
|
||||
|
@ -17,7 +17,7 @@ LL | yield();
|
|||
| ------- possible yield occurs here
|
||||
|
||||
error[E0626]: borrow may still be in use when generator yields (Mir)
|
||||
--> $DIR/yield-while-local-borrowed.rs:14:17
|
||||
--> $DIR/yield-while-local-borrowed.rs:15:17
|
||||
|
|
||||
LL | let a = &mut 3;
|
||||
| ^^^^^^
|
||||
|
@ -26,7 +26,7 @@ LL | yield();
|
|||
| ------- possible yield occurs here
|
||||
|
||||
error[E0626]: borrow may still be in use when generator yields (Mir)
|
||||
--> $DIR/yield-while-local-borrowed.rs:42:21
|
||||
--> $DIR/yield-while-local-borrowed.rs:43:21
|
||||
|
|
||||
LL | let b = &a;
|
||||
| ^^
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
|
||||
--> $DIR/yield-while-ref-reborrowed.rs:35:20
|
||||
--> $DIR/yield-while-ref-reborrowed.rs:36:20
|
||||
|
|
||||
LL | let mut b = || {
|
||||
| -- generator construction occurs here
|
||||
|
@ -8,8 +8,8 @@ LL | let a = &mut *x;
|
|||
...
|
||||
LL | println!("{}", x); //~ ERROR
|
||||
| ^ second borrow occurs here
|
||||
LL | b.resume();
|
||||
| - first borrow later used here
|
||||
LL | Pin::new(&mut b).resume();
|
||||
| ------ first borrow later used here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
use std::cell::Cell;
|
||||
use std::pin::Pin;
|
||||
|
||||
unsafe fn reborrow_shared_ref(x: &i32) {
|
||||
fn reborrow_shared_ref(x: &i32) {
|
||||
// This is OK -- we have a borrow live over the yield, but it's of
|
||||
// data that outlives the generator.
|
||||
let mut b = move || {
|
||||
|
@ -11,10 +12,10 @@ unsafe fn reborrow_shared_ref(x: &i32) {
|
|||
yield();
|
||||
println!("{}", a);
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
unsafe fn reborrow_mutable_ref(x: &mut i32) {
|
||||
fn reborrow_mutable_ref(x: &mut i32) {
|
||||
// This is OK -- we have a borrow live over the yield, but it's of
|
||||
// data that outlives the generator.
|
||||
let mut b = move || {
|
||||
|
@ -22,10 +23,10 @@ unsafe fn reborrow_mutable_ref(x: &mut i32) {
|
|||
yield();
|
||||
println!("{}", a);
|
||||
};
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
unsafe fn reborrow_mutable_ref_2(x: &mut i32) {
|
||||
fn reborrow_mutable_ref_2(x: &mut i32) {
|
||||
// ...but not OK to go on using `x`.
|
||||
let mut b = || {
|
||||
let a = &mut *x;
|
||||
|
@ -33,7 +34,7 @@ unsafe fn reborrow_mutable_ref_2(x: &mut i32) {
|
|||
println!("{}", a);
|
||||
};
|
||||
println!("{}", x); //~ ERROR
|
||||
b.resume();
|
||||
Pin::new(&mut b).resume();
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
|
||||
--> $DIR/yield-while-ref-reborrowed.rs:35:20
|
||||
--> $DIR/yield-while-ref-reborrowed.rs:36:20
|
||||
|
|
||||
LL | let mut b = || {
|
||||
| -- closure construction occurs here
|
||||
|
@ -8,7 +8,7 @@ LL | let a = &mut *x;
|
|||
...
|
||||
LL | println!("{}", x); //~ ERROR
|
||||
| ^ borrow occurs here
|
||||
LL | b.resume();
|
||||
LL | Pin::new(&mut b).resume();
|
||||
LL | }
|
||||
| - borrow from closure ends here
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
#![allow(unused_mut)]
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::marker::Unpin;
|
||||
use std::ops::Generator;
|
||||
use std::ops::GeneratorState::Yielded;
|
||||
use std::pin::Pin;
|
||||
|
||||
pub struct GenIter<G>(G);
|
||||
|
||||
impl <G> Iterator for GenIter<G>
|
||||
where
|
||||
G: Generator,
|
||||
G: Generator + Unpin,
|
||||
{
|
||||
type Item = G::Yield;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
match self.0.resume() {
|
||||
Yielded(y) => Some(y),
|
||||
_ => None
|
||||
}
|
||||
match Pin::new(&mut self.0).resume() {
|
||||
Yielded(y) => Some(y),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue