Here is a code snippet: I want to create a simple node chain, each node has a named path(character) to another one.
use std::collections::HashMap;
pub struct Node<'a> {
label: String,
paths: HashMap<char, &'a Node<'a>>,
}
impl<'a> Node<'a> {
pub fn new(state: String) -> Node<'a> {
Node {
label: state,
paths: HashMap::new(),
}
}
pub fn add_transition(&mut self, symbol: char, to: &'a Node) {
self.paths.entry(symbol).or_insert(to);
}
}
fn main() {
let mut i0 = Node::new("node0".to_string());
let mut i1 = Node::new("node1".to_string());
let mut i2 = Node::new("node2".to_string());
i0.add_transition('a', &i1);
i1.add_transition('b', &i2);
// i1.add_transition('c', &i0);
}
If the line i1.add_transition('c', &i0);
is commented out, the code compiles fine.
But if I add the line, everything will collapse with the error:
error[E0502]: cannot borrow `i1` as mutable because it is also borrowed as immutable
--> src/main.rs:27:5
|
26 | i0.add_transition('a', &i1);
| --- immutable borrow occurs here
27 | i1.add_transition('b', &i2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
28 |
29 | i1.add_transition('c', &i0);
| --- immutable borrow later used here
error[E0502]: cannot borrow `i1` as mutable because it is also borrowed as immutable
--> src/main.rs:29:5
|
26 | i0.add_transition('a', &i1);
| --- immutable borrow occurs here
...
29 | i1.add_transition('c', &i0);
| ^^^--------------^^^^^^^^^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
I am not trying to create a list here, what i concern is the mystery of immutable borrow and mutable borrow, i noticed there are many sample works fine even the book pointed out they don't work and theoretically not working code really works.
So, make the question simple: why the code can compile without errors if line 29 removed? In my opinion, the line 26 already has a immutable borrow of &i1 and line 27 has a mutable borrow of &i1, they should not be there at the same line(Rust book said so).