Cannot borrow var as mutable more than once at a time

Hello, I have this code:

path = &path[len..];

if let Some(node) = curr_node.find_child_with_starting_character(path.bytes().next().unwrap()) {
                    curr_node = node;
                    continue;
}
let node = Node::new(path, method,func, NodeKind::Static);
curr_node.add_child(node);

Here I have this error at the last line:

cannot borrow `*curr_node` as mutable more than once at a time
second mutable borrow occurs hererustcE0499

All this code is inside a loop, and curr_node is defined outside the loop, similar as follow:

let curr_node: &mut node;
loop {
 // the prec code 
}

Following are some parts of the node struct:


pub struct Node {
    pub prefix: String,
    pub method: Method,
    pub callback: Option<usize>,
    pub child_nodes: Vec<Node>,
    pub node_kind: NodeKind,
}

impl Node {
  pub fn find_child_with_starting_character(& mut self, character: u8) -> Option<&mut Node> {
        for node in self.child_nodes.iter_mut() {
          if node.prefix.as_bytes()[0] == character {
            return Some(node);
          }
        }
        None
  }
}

how can I fix it? What is the problem?

To help us help you, execute cargo check in a command line to get a better / more complete error message that you can copy and post here.

1 Like
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()).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.