Coder
Coder

Reputation: 1909

Cannot borrow `*self` as mutable because it is also borrowed as immutable in Match statement

Apologies, since this seems quite a popular question. I went through a bunch of examples.

  1. How do you borrow a mutable reference during a match? - the solution is not applicable since the get_mut(&0).unwrap() is not available for the self.head object.
  2. Mutable borrow followed by immutable borrow (cannot borrow as immutable because it is also borrowed as mutable) - doesn't provide much insight and redirects to Cannot borrow as mutable because it is also borrowed as immutable. This example does provide valuable learning that there can't be an immutable reference and then a mutable reference in a multi-line statement, but it doesn't still cover the case on a match statement.
  3. Why does refactoring by extracting a method trigger a borrow checker error? - is also closely related, but doesn't handle the specific requirement of the match statement. Again, perhaps obvious to someone experienced with Rust but not to me.

Hence my doubt:

use std::collections::HashMap;

#[derive(Debug)]
struct Node {
    word: String,
    next: Option<HashMap<char, Node>>,
}

impl Node {
    fn new(word: String) -> Self {
        Node {
            word,
            next: None,
        }
    }
}

#[derive(Debug)]
struct WordDictionary {
    head: Option<Node>,
}

impl WordDictionary {
    fn new() -> Self {
        WordDictionary {
            head: None,
        }
    }

    fn add_word(&mut self, word: String) {
        match &self.head {       // Issue here
            None => { /* Do something */ }
            Some(nd) => {           
                self.iterate(nd, word, 0);    // And here
            }
        }
    }

    fn iterate(&mut self, _parent_node: &Node, _word: String, _idx: usize) {
        // Do something
    }
}

#[allow(non_snake_case)]
fn main() {
    {
        let mut wordDictionary = WordDictionary::new();
        wordDictionary.add_word("bad".to_string());
        println!("{:?}", wordDictionary);
    }
}

Gives the following error:

⣿
Execution
Close
Standard Error
   Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
  --> src/main.rs:34:17
   |
31 |         match &self.head {
   |               ---------- immutable borrow occurs here
...
34 |                 self.iterate(nd, word, 0);
   |                 ^^^^^-------^^^^^^^^^^^^^
   |                 |    |
   |                 |    immutable borrow later used by call
   |                 mutable borrow occurs here

For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground` due to previous error

Playground

It would be great if someone can provide insight into this specific example or help point another answered example.

Thank you!

Upvotes: 2

Views: 2573

Answers (1)

Pavlo Myroniuk
Pavlo Myroniuk

Reputation: 344

First of all, I'm not sure that your iterate function signature is possible. Explanation: your function takes one mutable and one immutable reference at the same time. In Rust, this is not possible. You can have only one mutable or many immutable references. Because the iteration function has &mut self I suppose that you want to modify smth during the execution. To do that, only one &mut Node will be enough. Like here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c962831b569768f05599b99cdff597bd

Upvotes: 0

Related Questions