Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign upyield has a problem with lifetimes #45259
Comments
kennytm
added
the
A-generators
label
Oct 13, 2017
This comment has been minimized.
This comment has been minimized.
|
Well, this is a bit awkward: After looking at issue 44197 I tried to replace -match foo.i() {
+let i = foo.i();
+match i {in the code above, and the compilation suddenly worked fine. #![feature(conservative_impl_trait, generators, generator_trait)]
extern crate futures;
use std::ops::{ Generator, GeneratorState };
use futures::{ Async, future, Future };
struct Foo {
i: u8,
}
impl Foo {
fn i<'a>(&'a mut self) -> impl Future<Item = u8, Error = ()> + 'a {
future::ok(self.i)
}
}
fn run<'a>(foo: &'a mut Foo) -> impl Generator<Yield = (), Return = Result<u8, ()>> + 'a {
move || {
if false {
yield
}
let _ = {
let mut f = foo.i();
loop {
let poll = f.poll();
match poll {
Ok(Async::Ready(i)) => break i,
Ok(Async::NotReady) => yield,
_ => unreachable!(),
}
}
};
{
let mut f = foo.i();
let poll = f.poll();
match poll {
Ok(Async::Ready(i)) => Ok(i),
_ => unreachable!(),
}
}
}
}
fn main() {
let mut foo = Foo { i: 0 };
let mut g = run(&mut foo);
match g.resume() {
GeneratorState::Complete(Ok(i)) => println!("{}", i),
_ => unreachable!(),
}
}
|
This comment has been minimized.
This comment has been minimized.
Arnavion
commented
Oct 13, 2017
|
Reduced test case: #![feature(conservative_impl_trait, generators, generator_trait)]
use std::ops::Generator;
trait Tr { }
struct Foo;
impl Tr for Foo { }
struct Bar;
impl Bar {
fn baz<'a>(&'a mut self) -> impl Tr + 'a {
Foo
}
}
fn run<'a>(bar: &'a mut Bar) -> impl Generator<Yield = (), Return = ()> + 'a {
move || {
if false {
yield;
}
{
let _baz = bar.baz();
if false { yield; }
}
{
bar.baz();
}
}
}
fn main() {
} |
This comment has been minimized.
This comment has been minimized.
|
These are all due to borrows being considered live at a suspension point. @nikomatsakis You wrote the code that should detect these cases. @arielb1 also had some comments about it you should look at. |
This comment has been minimized.
This comment has been minimized.
|
@Zoxc, Are you saying that this is just the wrong error message or do you agree that this is a 'real' bug? |
This comment has been minimized.
This comment has been minimized.
|
It is just a wrong error message. |
This comment has been minimized.
This comment has been minimized.
|
I do not see why this code should not work. The mutual reference of |
This comment has been minimized.
This comment has been minimized.
|
There actually seem to be something interesting going on here. Here is a reduced test case: #![feature(generators)]
fn _run(bar: &mut i32) {
|| {
{
let _baz = &*bar;
yield;
}
*bar = 2;
};
}
fn main() {}
This program is not fundamentally unsafe and would compile if region inference had found a better lifetime for the reborrow. So I guess this is more unfortunate semantics than a bug, but the error message should still be improved. |
This comment has been minimized.
This comment has been minimized.
|
Thanks, @Zoxc for your explanation. I see now why this code won't compile. I don't know if it's possible to make the compiler inject some code after the |
This comment has been minimized.
This comment has been minimized.
|
@manuels I'm working on a way to make this work. |
This comment has been minimized.
This comment has been minimized.
|
This is basically non-lexical lifetimes. The borrow is inferred to be potentially live over a yield point, and therefore it's potentially live while the generator is used. |
This comment has been minimized.
This comment has been minimized.
|
Or you could attack the "both fn foo(x: &mut u32) {
// both `s` and `t` are live for the generator's lifetime, but within
// the generator they have distinct lifetimes.
move || {
{
let s = &mut *x;
yield;
*s += 1;
}
let t = &mut *x;
yield;
*t += 1;
};
} |
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Oct 17, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Oct 17, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Oct 17, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Oct 17, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Oct 21, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Nov 5, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Nov 5, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Nov 5, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Nov 5, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Nov 14, 2017
This comment has been minimized.
This comment has been minimized.
|
@Zoxc, thanks for taking care of this issue! Are there any updates (e.g. about blocking issues) on this bug? |
This comment has been minimized.
This comment has been minimized.
|
Apparently @arielb1 did something on the issue blocking immovable types. |
This comment has been minimized.
This comment has been minimized.
|
Great, thanks for the update! |
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Dec 22, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Dec 22, 2017
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Dec 23, 2017
This comment has been minimized.
This comment has been minimized.
|
So with
|
This comment has been minimized.
This comment has been minimized.
|
@manuels That is a separate bug so a new issue should be created for it. |
This comment has been minimized.
This comment has been minimized.
|
Ok, I was wondering, but the backtrace looked too complex to me to analyze it. Thanks, @Zoxc! |
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Jan 11, 2018
XAMPPRocky
added
T-lang
C-bug
labels
Jan 22, 2018
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Jan 23, 2018
Zoxc
added a commit
to Zoxc/rust
that referenced
this issue
Jan 23, 2018
This comment has been minimized.
This comment has been minimized.
|
This bug is fixed by #47353 and using |
manuels commentedOct 13, 2017
•
edited
When working with
futures-awaitI 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
futurescompletely. My current minimal example to reproduce this bug reads:For some reason the compiler complains:
@Arnavion's diagnosis is
I tried to have a look at the rust compiler's implementation of
std::ops::Generatorby I don't know enough to debug this problem.The fact that the compiler complains about the lifetime, however, is strange.