-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve lifetime error messages re: block suffixes and dropck #21875
Comments
The error shows exactly what is wrong in black and white... They may go out of scope at the same time, but the lifetime of I think this has to do with the fact that lifetimes are lexical, which is not always what we want, but it is the way it is currently. |
The problem here is that the old code used to compile, as of a few weeks ago - the set of permitted programs shrank. It certainly would be nice if programs like this were allowed. |
The message "does not live long enough" (from an English-language point of view) strictly means "the lifetime of the variable must be extended to cover more of the program", which is fairly non-specific. Having used rust a little since mid-Dec, my interpretation is "the extension of the lifetime should probably happen at the end, rust only complains when things don't live long enough". I've honestly no idea how I'd pick up that foo starting earlier than bar is a deal breaker without googling the error and finding this issue and http://users.rust-lang.org/t/why-how-lifetime-works-has-changed/256 |
Okay; it seems like this is a consequence of #21657, as aidanhs's link suggests. I no longer think this is a bug; it seems that this is the way Rust must behave. Issue #21657 changes the compiler to track lifetimes more carefully. For example, in code like this: {
let x: i32;
let y: i32;
let z: i32;
} the pre-change compiler would treat these all as having the same scope: the block that contains them. Post-change, Rust treats In the case of struct Grr<'a> {
r: &'a Box<i32>
}
impl<'a> Drop for Grr<'a> {
fn drop(&mut self) {
println!("dropping {}", *self.r);
}
}
#[test]
fn good_borrow01() {
let mut r;
let i = box 10i32;
r = Grr { r: &i };
assert_eq!(**r.r, 10);
} In this program, Note that you must sprinkle #[unsafe_destructor] all over the place to make this code compile, which seems exactly right: if this behavior is permitted, the language is not memory-safe. |
Yes, this is definitely caused by #21657. The If I understood it correctly, my premise is already wrong:
Because as @jimblandy mentions, they really don't. Instead, the code compiles like this: fn main() {
let foo;
{
let bar = 1337;
{
foo = &bar;
}
}
} And suddenly it all makes sense: Of course the I can think of several solutions:
|
Now things get weird: fn main() {
let foo: Box<&i32>;
let bar = 1337;
foo = Box::new(&bar);
{ foo; } // kill foo
foo; // error expected, foo was moved
bar; // no error, bar is still alive
} As expected,
It's the same error again! However, the last two lines show that |
A variable being moved from is not the same as its going out of scope, though. In any case, it looks to me as if this issue should be closed; the original behavior described is not a bug. |
It might not be a bug, but it's still far from perfect and could (should, in my opinion) be improved, e.g. in one of the ways I suggested above. |
Your example in #21875 (comment) might get addressed eventually as part of #6393 ; at least, that is the only way I can see us encoding the knowledge that And that change (#6393) may well happen at some point; but for now, we are coping with our more simplistic model of lifetimes. I don't think we're going to automatically reorder bindings to satisfy Pure destructors might happen, but I don't think they would actually address the example of #21875 (comment) In the end, I suspect the best way to approach this ticket is via improvements to the error messages, especially when it comes to the fallout from #21657 (but there are other places where borrowck error messages can be improved). |
cc #22321 |
It might be best to leave the precise error messages there: hearing about "block suffixes" gives an opportunity to learn the theory behind the borrow checking. But I agree more help is needed: for newcomers to Rust it's easy to misread the compiler's error, since they might not be thinking correctly about lifetimes. So I'd suggest adding a
I'm only a beginner, so I might be overlooking cases of incorrect lifetimes where the solution is different. The compiler already outputs similar messages for temporary variables, which is nice:
|
This appears to have been improved at some point, trying the original code on the playground gives
the block suffix part of the message is gone and a |
I think the note is close enough that we can close this. Lifetime errors are always non-ideal and we have a lot of issues about improving them (I think, at least) and this one is specific enough that the note (values ... dropped in opposite order) solves it. |
foo
andbar
go out of scope simultaneously, so the error can only refer to the fact thatbar
's lifetime begins afterfoo
's lifetime. But that still doesn't make sense, asbar
is alive when the reference to it is assigned tofoo
.I'm using the nightly builds from the Ubuntu PPA:
The text was updated successfully, but these errors were encountered: