Closed
Description
Consider the example:
#![feature(generators, conservative_impl_trait, generator_trait)]
use std::ops::Generator;
fn test<'a>(val: u32) -> impl Generator<Yield = u32, Return = u32> + 'a {
move || { // returned generator state has lifetime 'a
let mut x = val; // variable x is in the generator state and, hence, it has lifetime 'a
let y = &mut x; // but y, (which pointing to x with lifetime 'a) doesn't have lifetime 'a
yield 1;
*y += 1;
yield 2;
*y += 1;
yield 3;
return *y;
}
}
fn main() {
let mut gen = test(1);
println!("{:?}", gen.resume());
println!("{:?}", gen.resume());
println!("{:?}", gen.resume());
println!("{:?}", gen.resume());
}
it won't compile with error:
error[E0597]: `x` does not live long enough
--> src/main.rs:8:22
|
8 | let y = &mut x;
| ^ borrowed value does not live long enough
...
22 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 5:1...
--> src/main.rs:5:1
|
5 | / fn test<'a>(val: u32) -> impl Generator<Yield = u32, Return = u32> + 'a {
6 | | move || {
7 | | let mut x = val;
8 | | let y = &mut x;
... |
22 | | }
23 | | }
| |_^
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
andreytkachenko commentedon Jan 22, 2018
I am sure that it is possible despite that generator may be moved and it actual address will change. Maybe create some sort of
virtual
pointers, which will be dependent on struct base address and rust will have vtable for derefecencing such pointers at runtime. On each struct move new address will be updated in such table.andreytkachenko commentedon Jan 23, 2018
The best solution for that problem, by my mind, is to track, on compile time, the generator state, and fail compilation when it will be moved while there are some references pointing to it part. Very similar how rust tracking the variables.
andreytkachenko commentedon Jan 24, 2018
Has to be fixed by #45337