Just when I thought I had lifetimes figured out...
The compiler won't let this happen:
fn main() {
let mut thing = Thing();
let mut a = MutReference { data: &mut thing };
a.another_reference_mut();
a.another_reference_mut();
}
struct Thing();
struct MutReference<'a> {
data: &'a mut Thing,
}
impl<'a> MutReference<'a> {
fn another_reference_mut(&'a mut self) -> MutReference<'a> {
MutReference { data: self.data }
}
}
The error message is rather confusing:
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:6:5
|
5 | a.another_reference_mut();
| ------------------------- first mutable borrow occurs here
6 | a.another_reference_mut();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
What does he mean by "first borrow later used here"? Clearly the first borrow is not used there – it's dropped on line 5 and never used again. Even wrapping that line in {} does not help.
After some tinkering, I found out that creating a separate lifetime for the function fixes the problem:
impl<'a> MutReference<'a> {
fn another_reference_mut<'b>(&'b mut self) -> MutReference<'b> {
MutReference { data: self.data }
}
}
('b may also be elided here)
Now I'm pretty sure that this is the correct solution, but I'm still not sure why the old code wasn't working. It seems I had written in some lifetime constraint I did not intend, but I don't know how to properly reason about the lifetimes in this situation, and the compiler error doesn't help.
My understanding was that, when the same lifetime is used on several "input" references and an "output" reference, all it means is that the "output" reference cannot outlive any of the input references... but it seems something else is going on here – it's as if the &'a mut self input reference was "forcing" the return value to live longer than it normally would? How does this work? What was wrong with my old code?