error[E0502]: cannot borrow `*self` as immutable because `self.data` is also borrowed as mutable


#1
pub struct Derp {
    data: Vec<u32>,
}

impl Derp {
    fn new() -> Derp {
        Derp {
           data: Vec::new(),
        }
    }

    pub fn add_stuff(&mut self) {
        self.data.push(10);
        self.data.push(11);
    }

    pub fn update_stuff(&mut self) {
       for entry in self.data.iter_mut() {
          *entry = self.calc();
       }
    }

    pub fn calc(&self) -> u32 {
       12
    }
}

fn main() {
   let mut derp = Derp::new();
   derp.add_stuff();
   derp.update_stuff();
}

Hi

The above is a simplified version of what I’m trying to do which is gather data in to a vec, and at some point in the future I will need to iterate for the vec and change the data by calling self.function() on each vec entry.

So this results in

error[E0502]: cannot borrow `*self` as immutable because `self.data` is also borrowed as mutable
|
|        for entry in self.data.iter_mut() {
|                     --------- mutable borrow occurs here
|            *entry = self.calc() ;
|                     ^^^^ immutable borrow occurs here
|        }
|        - mutable borrow ends here

I suppose I can make a temp vec and store the updated values in that, then make the temp vec be self.data, but there must be a better way then that?

And 2 general questions about this

  1. If self.data is whats mutable, shouldn’t you be allowed to use other parts of self that don’t touch self.data? It appears you are allowed to use self.variable (other then self.data), but not self.function().
  2. self.calc() is an immutable borrow which would imply the function cant change self. what harm would come from allowing this barrow/function call?

thanks!
jim


#2
  1. fn calc(&self) borrows all of Derp not just the fields that you’re going to use. It could be doable; the borrowchecker just doesn’t work like that currently.
  2. one problem is data races. You get a read access to something that’s known to be mutably aliased. &self doesn’t just mean you can’t mutate the value. It also guarantees the value can’t be mutated by another piece of code (potentially in another thread) or be deallocated while you hold the reference.

The simplest solution is to use a traditional for loop to minimize the scope where data is mutably borrowed:

for i in 0..self.data.len() {
    self.data[i] = self.calc();
}

#3

Thanks for the explanations.

jim


#4

It’s not clear that the calc method needs access to self at all. Certainly not in the example you provided. If that is really the case, you can use an Associated Function. If there are some values from the instance you need to use in calc(), you could pass them as arguments.