I have the following code:
struct Baz {
x: usize,
y: usize,
}
struct Bar {
baz: Baz,
}
impl Bar {
fn get_baz_mut(&mut self) -> &mut Baz {
&mut self.baz
}
}
struct Foo {
bar: Bar,
}
impl Foo {
fn foo(&mut self) -> Option<&mut Baz> {
for i in 0..4 {
let baz = self.bar.get_baz_mut();
if baz.x == 0 {
return Some(baz);
}
}
None
}
}
Rust Playground
It fails to compile with:
error[E0499]: cannot borrow `self.bar` as mutable more than once at a time
--> src/main.rs:23:23
|
23 | let baz = self.bar.get_baz_mut();
| ^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
29 | }
| - mutable borrow ends here
However, if I return Some(baz.x)
from Foo::foo
(and change the return type to Option<usize>
), the code compiles. This makes me believe the problem is not with the loop even though the compiler seems to indicate so. More specifically, I believe the local mutable reference baz
would go out of scope at the next iteration of the loop, causing this to be a non-problem. What is the lifetime problem with the above code?
The following questions are similar:
However, they deal with explicitly declared lifetimes (and specifically these explicit lifetimes are part of the answer). My code omits these lifetimes so removing them is a non-solution.
It does not work because returning a borrowed value extends the borrow to the end of the function.
See here for some useful details.
This works with non-lexical lifetimes with the 1.27 nightly version:
#![feature(nll)]
struct Baz {
x: usize,
y: usize,
}
// ...
The non-lexical lifetimes RFC explains the actual working of lifetimes:
Problems arise however when you have a reference that spans multiple statements. In that case, the compiler requires the lifetime to be the innermost expression (which is often a block) that encloses both statements, and that is typically much bigger than is really necessary or desired
rustc nightly 1.28
As pointed out by @pnkfelix, the non-lexical lifetimes implementation starting from nightly 1.28 no longer compiles the above code.
There is however a long-term plan to (re)-enable a more powerful NLL analysis.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With