Borrowing self twice in a single expression sometimes leads to an error

Viewed 37

The following code fails to compile:

struct Foo {
    values: Vec<i32>,
}

impl Foo {
    fn len(&self) -> usize {
        todo!()
    }
    
    fn set(&mut self) {
        self.values[self.len()] = 0;
    }
}
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/lib.rs:12:21
   |
12 |         self.values[self.len()] = 0;
   |         ------------^^^^^^^^^^-
   |         |           |
   |         |           immutable borrow occurs here
   |         mutable borrow occurs here
   |         mutable borrow later used here

Playground

There is a number of ways to fix this error, the most perplexing for me is this:

    fn set(&mut self) {
        self.set_len(self.len()); // <----- double borrow again?
    }
    
    fn set_len(&mut self, index: usize) {
        self.values[index] = 0;
    }

Playground

Why does the first case fail to compile, while the second compiles? It seems to me that in both cases self is borrowed twice in a single expression - one time mutably, and one time immutably. Is there a subtle reason for this that I am unable to see, or is it a borrow checker quirk?

1 Answers

It's a borrow checker quirk. There's a special rule implemented to solve the "call mutable method where an argument is the result of another method" issue.

There's no special rule for "access a member and do something with that where the result of a method is needed". The member is borrowed first, and then the whole object can't be borrowed for the method call anymore.

Related