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