Borrow for if doesn't end until after else?


#1

Hi,

I get a strange error when compiling this code:

use std::str::Chars;
use std::collections::HashMap;

struct Node {
    words : Vec<String>,
    children: HashMap<char, Node>
}

fn insert_internal(word : &str, remaining: &mut Chars, node: &mut Node) {
    match remaining.next() {
        Some(ch) => {
            if let Some(next_node) = node.children.get_mut(&ch) {
                insert_internal(word, remaining, next_node);
                return;
            } else {
                let mut next_node = Node {words: Vec::new(), children: HashMap::new()};
                insert_internal(word, remaining, &mut next_node);
                node.children.insert(ch, next_node);
            }
        }
        None => node.words.push(word.to_string())
    }
}

fn main() {
}

The error:

src/main.rs:18:17: 18:30 error: cannot borrow `node.children` as mutable more than once at a time
src/main.rs:18                 node.children.insert(ch, next_node);
                               ^~~~~~~~~~~~~
src/main.rs:12:38: 12:51 note: previous borrow of `node.children` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `node.children` until the borrow ends
src/main.rs:12             if let Some(next_node) = node.children.get_mut(&ch) {
                                                    ^~~~~~~~~~~~~
src/main.rs:19:14: 19:14 note: previous borrow ends here
src/main.rs:12             if let Some(next_node) = node.children.get_mut(&ch) {
...
src/main.rs:19             }

If I change the file like this:

 -           } else {
 +           } 
               let mut next_node = Node {words: Vec::new(), children: HashMap::new()};
                insert_internal(word, remaining, &mut next_node);
                node.children.insert(ch, next_node);
 -           }

Then it compiles just fine.

That suggests to me that the borrow doesn’t end until after the else-clause (even though it is scoped to the if-clause), which seems odd.

Cheers,
Brian


#2

It looks like you’ve run into a known limitation with the length of borrows in if tests. That’s been wrapped into a new issue. Niko mentioned it as one of the priorities for post-1.0 so hopefully it’ll see some action soon!