2

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.

Kyle L.
  • 315
  • 2
  • 6
  • 1
    https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=8e6e5ad933e6734d0f8ead1036a7f258 – PiRocks Oct 29 '21 at 15:34
  • Hi, John. I saw your proposed edits to the code in link. The simplified version certainly doesn't need access to &self, but in my fuller version of the code I do. So, assuming I need to access fields in &self, what would you propose fix the issue and why? Thanks! – Kyle L. Oct 29 '21 at 15:51
  • E-net4, it doesn't. That one speaks to immutable to mutable. In my case I'm trying to go from mutable to immutable. – Kyle L. Oct 29 '21 at 15:53
  • 1
    The problem and solution are the same: you need to drop the mutable borrow in `obj`, and only then rely on immutable borrows to call the method `do_action`. Without that, it is not possible to call that method. – E_net4 Oct 29 '21 at 15:56
  • Is it acceptable to access the object again: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=80092546c0b4c01177463f466f4042c7 – user4815162342 Oct 29 '21 at 16:15
  • Got it! Thank you for pointing me in the right direction: I added a redefined scope that dropped the mutable reference and added an immutable one. Thank you, E_net4! See the following playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=97a1cbef0f66b1857c65d605975865a4 – Kyle L. Oct 29 '21 at 16:18

0 Answers0