#Stuck on double mutable borrow

21 messages · Page 1 of 1 (latest)

minor rampart
#
            let edges = &mut trie.next;
            let mut find_node;

            find_node = edges.iter_mut().find(|node| node.0 == ch);

            match find_node {
                None => create_new_node(ch, edges),
                Some(node) => &node.1
            }
        }```

This is my error
```error[E0499]: cannot borrow `*edges` as mutable more than once at a time 
   --> src\main.rs:53:45                      
    |                                         
 46 |         fn get_or_create_node(ch: char, trie: &mut Trie) -> &Box<Trie> {  
    |                                               - let's call the lifetime of this reference `'1` 
 ...                   
 50 |             find_node = edges.iter_mut().find(|node| node.0 == ch); 
    |                         ---------------- first mutable borrow occurs here 
 ...  
 53 |                 None => create_new_node(ch, edges),
    |                                             ^^^^^ second mutable borrow occurs here
 54 |                 Some(node) => {
 55 |                     &node.1     
    |                     ------- returning this value requires that `*edges` is borrowed for `'1`
                                                                           ```

I just can't think of an alternative. Really, I just want to check if a vector contains an element, and if not, mutate it. So I have `edges` twice. How do I only use it once?
glossy drift
#

Assuming edges has a type like Vec<(char, Box<Trie>)>, you can get an index instead of a reference and then use the index:```rust
fn get_or_create_node(ch: char, trie: &mut Trie) -> &Box<Trie> {
match trie.next.iter().position(|node| node.0 == ch) {
None => create_new_node(ch, &mut trie.next),
Some(node) => &trie.next[node].1,
}
}

#

position gives the index.

minor rampart
#

I don't understand this code, lol.

The first trie is an immutable borrow, right? What's the second trie?

glossy drift
#

Yes, it borrows it to find the position of ch in trie.next.

minor rampart
#

Bacon has thrown no errors so that's good haha

glossy drift
#

After it finds the position, it stops the borrow.

#

Then, you get None if there was nothing with ch in it.

#

And note the mutable reference only exists immediately when it's needed.

#

&mut trie.next right when it's used rather than sitting in a variable since the start of the function.

#

That way, you don't have immutable references and mutable references kind of tripping over each other.

#

Indexes are also a nice trick to avoid getting references when you're getting reference conflicts.

minor rampart
#

Actually I think I was wrong, position does borrow mutably

#

That stops the mutable borrow

#

Because the index can be copied?

glossy drift
#

Do you still have iter_mut?

minor rampart
#

No I copied your code.

glossy drift
minor rampart
#

Okay, I think I see the difference then. Rather than keep a reference around, we're keeping an index around instead

glossy drift
#

Right.

minor rampart
#

Okay I'll have to digest this trick haha. I wouldn't have thought of that. Thank you!