error[E0499]: cannot borrow `*curr_node` as mutable more than once at a time
--> src/router/radix_tree.rs:101:17
|
95 | if let Some(node) = curr_node.find_child_with_starting_character(path.bytes().next().unwrap()) {
| --------- first mutable borrow occurs here
...
101 | curr_node.add_child(node);
| ^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
I see. This might be a quite subtle problem, reaching the limitations of Rust’s current borrow checker.
You are conditionally assigning a value (node in the Some(node) pattern) based on a mutable borrow (the value in curr_node) to curr_node itself. Seems like this pattern could probably be totally fine in principle, but the borrow-checker doesn’t like the way that the borrow of curr_node for the .find_child_with_starting_character has to be shorter or longer depending on whether the result is Some or None.
If you want to fully verify that this is just a limitation of the current borrow checker, see what happens on a nightly compiler with polonius enabled (cargo +nightly rustc -- -Zpolonius).
In any case, but particularly if the code compiles with polonius, a workaround that might work is to split up find_child_with_starting_character a bit. Make it return an Option<usize> instead specifying the index of the node that’s found, and add another method e.g. fn get_child_mut(&mut self, usize) that can return the &mut Node you need. Then use something like
if let Some(index) = curr_node.find_child_with_starting_character(path.bytes().next().unwrap()) {
curr_node = curr_node.get_child_mut(index);
continue;
}
You can get the index by using enumerate, i.e. for (index, node) in self.child_nodes.iter_mut().enumerate(). You could probably even refactor find_child_with_starting_character to take &self (and use .iter() instead of .iter_mut()).