Why can I get multiple mutable references to a variable in Rust without using unsafe code?

Viewed 369

I'm reading through the Rust book, and it said the following in section 4.2:

At any given time, you can have either one mutable reference or any number of immutable references.

However, I was experimenting and discovered that I actually can have more than one mutable reference in the same scope without using any unsafe code:

fn make_mut(x: &mut i32) -> &mut i32 {
    x
}

fn main() {
    let mut i = 1;
    let ir = &mut i;
    let ir2 = make_mut(ir);
    *ir2 = 2;
    println!("{}", *ir);
}

Output:

2

What's going on here? Was the Rust book oversimplifying things? Is there a better source of information on the Rust borrow checker geared for inexperienced Rust programmers than the Rust book?

1 Answers

Mutable references are non-Copy, so after you passed ir to make_mut it was moved and does not exist any more:

fn make_mut(x: &mut i32) -> &mut i32 {
    x
}

fn main() {
    let mut i = 1;
    let ir = &mut i;
    let ir2 = make_mut(ir);
    *ir = 3; // error here
    *ir2 = 2;
    println!("{}", *ir);
}

In your particular case, reborrowing happens with ir; that's how Rust modifyies your code:

fn make_mut(x: &mut i32) -> &mut i32 {
    x
}

fn main() {
    let mut i = 1;
    let ir = &mut i;
    let ir2 = make_mut(&mut *ir); // rust replaces raw `ir` with reborrowed mutable reference to dereferenced `ir`
    *ir2 = 2;
    println!("{}", *ir);
}

There will still be a compile error if you try to use both mutable references at once.

Related