Consider this code, ignoring the warnings:
fn main() {}
pub struct TreeNode {
subs: Vec<TreeNode>,
}
impl TreeNode {
pub fn do_something(&mut self) {
if let Some(changed_node) = self.enum_node(&|_| true) {
// Closure in real program is much more complicated and it really mutates its parameter
self.enum_node(&|_| false); // Again, real closure is more complicated
};
}
fn enum_node<'a, F>(&'a mut self, f: &F) -> Option<&'a Self>
where
F: Fn(&mut Self) -> bool,
{
if f(self) {
Some(self)
} else {
for sub in &mut self.subs {
if let Some(n) = Self::enum_node(sub, f) {
return Some(n);
}
}
None
}
}
}
The sense of the function enum_nodes
is to enumerate nodes of the tree, and if the closure f
returns true
on some node, stop enumerating and return a reference to that node.
It gives a compiler error:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:11:13
|
9 | if let Some(changed_node) = self.enum_node(&|_| true) {
| ---- first mutable borrow occurs here
10 | // Closure in real program is much more complicated and it really mutates its parameter
11 | self.enum_node(&|_| false); // Again, real closure is more complicated
| ^^^^ second mutable borrow occurs here
12 | };
| - first borrow ends here
I realize that
- This problem may be solved (I didn't actually try) by using
RefCell
- The lifetime of the first borrow of
self
is prolonged because the lifetime ofenum_node
'sself
parameter and return value are the same, and I assign the return value to thechanged_node
.
If I rewrite lines 9-12 as:
self.enum_node(&|_| true);
self.enum_node(&|_| false);
then it compiles because the lifetime of the first borrow of self
ends immediately after the first call to enum_node
.
That is not my question.
After the first call to enum_node
ends, the only way to mutate self
is via the returned value i.e. changed_node
, which it is immutable. Why does the compiler continue to count the borrow as mutable, is it logical?
How can I understand this behavior of the compiler?