Search code examples
rusttypesmutableborrow-checker

Mutable Borrows Inconsistency


The following program_pass compiles in Rust.

fn main() {
    let mut x = 0;
    let mut y = &mut x;
    let mut z = &mut y;
    let mut last = &mut z;

    let mut alt_y = &mut x;
    let mut alt_z = &mut alt_y;

    z = &mut alt_y;  // *last = &mut alt_y;

}

The following program_error does not.

fn main() {
    let mut x = 0;
    let mut y = &mut x;
    let mut z = &mut y;
    let mut last = &mut z;

    let mut alt_y = &mut x;
    let mut alt_z = &mut alt_y;

    *last = &mut alt_y;   // z = &mut alt_y;

}

What is violated in program_error, while not in program_pass? Just started, but this is really going against what I thought to be my understanding of Rust.


Solution

  • It's not inconsistency, it is is a intended behavior instead.
    In first case, no mutable reference is being used. Effectively no issue, so rust compiler is happy.

    In second case the rust compiler sees that mutable reference last is being dereferenced so it is taken as value access. And as we know rust doesn't allow the two mutable borrows.

    Reference: Deref

    To prove my point have tweaked your program a bit

    fn main() {
        let mut x = 0;
        let mut y = &mut x;
        let mut z = &mut y;
        let mut last = &mut z;
    
        let mut alt_y = &mut x;
        let mut alt_z = &mut alt_y;
    
        // notice the RHS here assigning 
        // mutable reference of i32 literal
        *last = &mut &mut 4;
        //                ^ not related to x anyhow
    }
    

    And now the error will reveal the reason behind the issue\

    error[E0499]: cannot borrow `x` as mutable more than once at a time
      --> src/main.rs:7:21
       |
    3  |     let mut y = &mut x;
       |                 ------ first mutable borrow occurs here
    ...
    7  |     let mut alt_y = &mut x;
       |                     ^^^^^^ second mutable borrow occurs here
    ...
    11 |     *last = &mut &mut 4;
       |     ------------------- first borrow later used here
    

    enter image description here