'Does it mean that a struct can't use other FnMut method after using a FnMut method?
the minimal example is this(Playground)
#[derive(Debug)]
struct Node {
id: usize,
subs: Vec<Node>,
}
impl Node {
fn refmut_nth_subnode(&mut self, n:usize)->Option<&mut Node> {
if self.subs.is_empty() {
return None;
}
else {
return Some(&mut (self.subs[n]))
}
}
}
pub struct SearchStack<RefmutNodeType> {
path: Vec<RefmutNodeType>,
}
impl<RefmutNodeType> SearchStack<RefmutNodeType> {
pub fn push(&mut self, node:RefmutNodeType) {
self.path.push(node);
}
pub fn last(&mut self)->&mut RefmutNodeType {
let end_index = self.path.len()-1;
&mut (self.path[end_index])
}
}
fn main() {
let mut node = Node{id:0, subs:vec![Node{id:1, subs:Vec::new()}]};
let mut lastnode = &mut node;
let mut stack = SearchStack{path:Vec::new()};
loop {
stack.push(lastnode); // move
match stack.last().refmut_nth_subnode(0) {
Some(node) => {
lastnode = node; // reinit
continue;
},
None => {
break;
}
}
}
}
The compiler says that stack is mutably borrowed twice. I anticipate that the method push will drop the &mut self after it's over, and then I can pass the &mut self to last method. But the compiler prevent me from doing so. While the second error looks seems to be similar. What is the cause of this problem?
While the full error is here:
error[E0499]: cannot borrow `stack` as mutable more than once at a time
--> src/main.rs:35:9
|
35 | stack.push(lastnode); // move
| ^^^^^^^^^^^--------^
| | |
| | first borrow later used here
| second mutable borrow occurs here
36 | match stack.last().refmut_nth_subnode(0) {
| ------------ first mutable borrow occurs here
error[E0499]: cannot borrow `stack` as mutable more than once at a time
--> src/main.rs:36:15
|
36 | match stack.last().refmut_nth_subnode(0) {
| ^^^^^^^^^^^^ `stack` was mutably borrowed here in the previous iteration of the loop
For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground` due to 2 previous errors
Solution 1:[1]
The problem is not that stack.push() is holding a mutable borrow preventing stack.last() from being called, the problem is that the borrow by stack.last() is extended because of the assignment to lastnode and so stack.push() isn't allowed to borrow the stack mutably.
Lifetime elision allows you to omit the lifetimes on the last() method. What you have here is equivalent to this:
pub fn last<'a>(&'a mut self)->&'a mut RefmutNodeType {
That is, the references have the same lifetime. This means storing the reference returned by last() requires extending the lifetime of the mutable borrow on the stack.
lastnode = node;
This line is the culprit. You can't hold a mutable reference to an element of a collection and modify the collection; this can cause a dangling reference if the collection is resized, for example.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | cdhowie |
