Closed
Description
When working with futures-await
I ran into a problem with lifetimes. @Arnavion was able to pin it down to the implementation of generators.
I simplified the code and got rid of futures
completely. My current minimal example to reproduce this bug reads:
#![feature(conservative_impl_trait, generators, generator_trait)]
use std::ops::{ Generator, GeneratorState };
struct Foo {
i: u8,
}
impl Foo {
fn i<'a>(&'a mut self) -> u8 {
self.i += 1;
self.i
}
}
fn run<'a>(foo: &'a mut Foo) -> impl Generator<Yield = (), Return = u8> + 'a {
move || {
if false {
yield
}
let _ = {
loop {
match foo.i() {
i if i == 0 => break i,
i if i == 1 => yield, // Error disappears when removing this line!
_ => unreachable!(),
}
}
};
{
match foo.i() {
i if i == 0 => i,
_ => unreachable!(),
}
}
}
}
fn main() {
let mut foo = Foo { i: 0 };
let mut g = run(&mut foo);
match g.resume() {
GeneratorState::Complete(i) => println!("{}", i),
_ => unreachable!(),
}
}
For some reason the compiler complains:
error[E0499]: cannot borrow `*foo` as mutable more than once at a time
--> test.rs:24:23
|
24 | match foo.i() {
| ^^^ mutable borrow starts here in previous iteration of loop
...
38 | }
| - mutable borrow ends here
error[E0499]: cannot borrow `*foo` as mutable more than once at a time
--> test.rs:33:19
|
24 | match foo.i() {
| --- first mutable borrow occurs here
...
33 | match foo.i() {
| ^^^ second mutable borrow occurs here
...
38 | }
| - first borrow ends here
error: aborting due to 2 previous errors
@Arnavion's diagnosis is
It appears to be a bug in generators arising because
Foo::i()
returns a value bounded by self's lifetime and there is a yield point while it's borrowed.
I tried to have a look at the rust compiler's implementation of std::ops::Generator
by I don't know enough to debug this problem.
The fact that the compiler complains about the lifetime, however, is strange.