How to fix `cannot borrow `*self` as mutable because it is also borrowed as immutable`

#[derive(Default)]
pub struct Module {
    section: Section
}

#[derive(Default)]
pub struct Section {
    pub code: Vec<Code>
}

#[derive(Default)]
pub struct Code{}

impl Module {

    pub fn run(&mut self, _code: &Vec<Code>){
        // self must be mut 
    }

}


fn main() {

    let mut module = Module::default();
    let code = &module.section.code;
    module.run(code);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `module` as mutable because it is also borrowed as immutable
  --> src/main.rs:27:5
   |
26 |     let code = &module.section.code;
   |                -------------------- immutable borrow occurs here
27 |     module.run(code);
   |     ^^^^^^^---^^^^^^
   |     |      |
   |     |      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` (bin "playground") due to previous error

Why do you need to pass in a reference to code separately, when it's already a member of self?

4 Likes

Unfortunately &mut self means exclusive access to all of self, including all its fields and items, recursively.

There are a few possible workarounds:

  1. Instead of passing code as a reference, pass some other way to identify it, like usize index in the Vec.

  2. Instead of &mut self, make it a "static" method without self and pass it all fields it needs individually. When you borrow separate struct fields within one function, the borrow checker understands they don't overlap.

  3. Use &self and interior mutability like Mutex or RefCell around fields you need to mutate. In Rust & is shared, but still can mutate, you just need a runtime check for mutability.

4 Likes

because the run method be invoked directly by pass code sometime, this is necessary.

in fact , i think the compiler can analyze that the code owned by self