Mutable borrow followed by immutable borrow (cannot borrow as immutable because it is also borrowed as mutable)

Viewed 581

I have reviewed a number of similar questions in Rust, but haven't found one that addresses the specific problem I have run into (most seem to refer to immutable to mutable issues, when my issue is the reverse). I am making a call to a function that has an immutable &self as its target parameter, yet the original target is owned mutable. I have tried a number of different things, but I am coming to the conclusion that I am missing something fundamental in my mental model that explains what I am doing wrong.

Here is the simplified code (Playground Link):

struct Object {
    value: bool,
}

struct Container {
    items: Vec<Object>,
}

impl Container {
    fn do_action(&self, w: &Object) {
        println!("value: {}", w.value);
    }
}

fn run_main() {
    let mut container = Container { items: Vec::new() };
    container.items.push(Object { value: false });

    // mutable borrow here
    let obj: &mut Object = container.items.get_mut(0).unwrap();
    obj.value = true;

    // immutable borrow here
    container.do_action(obj);
}

The resulting error is:

error[E0502]: cannot borrow `container` as immutable because it is also borrowed as mutable
  --> src/immutable_borrow_when_already_mutable.rs:24:6
   |
20 |     let obj: &mut Object = container.items.get_mut(0).unwrap();
   |                            --------------- mutable borrow occurs here
...
24 |     &container.do_action(obj);
   |      ^^^^^^^^^           --- mutable borrow later used here
   |      |
   |      immutable borrow occurs here

I have read numerous online resources, but I am still not seeing what I am doing wrong. I have been unable to redefine the variable as mutable using (&*). Any suggestions and pointers as to what I am missing are greatly appreciated.

It would be helpful to also know, why isn't mutable->immutable allowed by the compiler?

Clarification: The simplified code sample do_action doesn't need access to &self. However assume I do need access to fields in &self.

0 Answers
Related