Jomy
Jomy

Reputation: 558

Cannot borrow as immutable because it also borrowed as mutable

I have the following minimal example to reproduce this issue:

fn main() {
    let mut vec = Vec::from(["Hello"]);
    let mut some_struct = SomeStruct { field: "World" };
    some_struct.doSomething(&mut vec);
    
    println!("{:?}", vec);
}

struct SomeStruct<'a> {
    field: &'a str
}

impl<'a> SomeStruct<'a> {
    fn doSomething(&mut self, vec: &'a mut Vec<&'a str>) {
        vec.push(self.field);
    }
}

(obviously, doSomething doesn't need to take a mutable reference to self in this example, but I do need a mutable reference in the original code)

When I run the above example, I get the following errror:

error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable
  --> src/main.rs:22:22
   |
20 |     some_struct.doSomething(&mut vec);
   |                             -------- mutable borrow occurs here
21 |
22 |     println!("{:?}", vec);
   |                      ^^^
   |                      |
   |                      immutable borrow occurs here
   |                      mutable borrow later used here
   |
   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)

How can I print out the vec after it being borrowed mutably by doSomething?

I've tried cloning vec, RefCell, but nothing seems to work.

Upvotes: 1

Views: 4662

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 70850

The problem is the &'a mut Vec<...>. Repeating lifetimes is often wrong. In this case, you tell Rust "I want to borrow vec for 'a". But 'a is determined by self.field, and is inferred to be 'static here (or not; it doesn't really matter. The most important part is that it is inferred to be longer/equal to the lifetime of self, because otherwise self would hold a dangling reference). Now, by borrowing vec for 'a, you prevent use of it at least until self is destroyed.

If you remove the 'a lifetime from vec, it works:

fn doSomething(&mut self, vec: &mut Vec<&'a str>) {
    vec.push(self.field);
}

Upvotes: 3

Related Questions