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

Issue

This Content is from Stack Overflow. Question asked by rubo

The folliwing code fails to compile:

#[derive(Default)]
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());
    }
    
    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?



Solution

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.


This Question was asked in StackOverflow by rubo and Answered by Sebastian Redl It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?