Description
I've been playing around with a singly-linked-list. It turns out that this method, which I had hoped might compile with help of non-lexical-lifetimes, does not compile:
struct Recursive {
child: Option<Box<Recursive>>
}
impl Recursive {
fn mut_back(&mut self) -> &mut Self {
let mut node = self;
while let Some(child) = node.child.as_mut() {
node = child
}
node
}
}
The error is stating that the borrow for node.child
overlaps with the returned borrow of node
, as seen below:
error[E0499]: cannot borrow `*node` as mutable more than once at a time
--> src/lib.rs:11:13
|
6 | fn mut_back(&mut self) -> &mut Self {
| - let's call the lifetime of this reference `'1`
7 | let mut node = self;
8 | while let Some(child) = node.child.as_mut() {
| ---------- first mutable borrow occurs here
...
11 | node
| ^^^^
| |
| second mutable borrow occurs here
| returning this value requires that `node.child` is borrowed for `'1`
error: aborting due to previous error
There is a very similar implementation of mut_back()
which does compile:
impl Recursive {
fn mut_back_good(&mut self) -> &mut Self {
let mut node = self;
while let Some(ref mut child) = node.child {
node = child
}
node
}
}
What I think is going on to cause the first implementation to fail is the call to child.as_mut()
. Presumably due to autoref this creates a new unique borrow on node.child
.
In the second case, I understand that the ref mut
binding means we're also creating a unique borrow on node.child
. But in this case the borrow checker doesn't think this new unique borrow is a problem.
It seems to me that the compiler should be able to treat these two implementations equally?