2

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
jrpear
  • 232
  • 2
  • 6

1 Answers1

1

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.

Dmitry
  • 1,426
  • 5
  • 11
  • It's still dereferenced in `println!("{}", *ir);` though. Does it go into some weird half-existing state after being moved? Schrodinger's ref? – jrpear Apr 06 '21 at 19:09
  • I've updated my answer to explain a little bit about reborrowing. – Dmitry Apr 06 '21 at 19:13
  • Ah okay saw your edit. I haven't heard of reborrowing. Do you know where I might be able to read more about it? I'm on Ch. 19 of the Rust book and I don't think it's been mentioned. – jrpear Apr 06 '21 at 19:15
  • Okay for anyone reading this in the future, this issue may be helpful: https://github.com/rust-lang/reference/issues/788 – jrpear Apr 06 '21 at 19:22
  • It's just a little trick of Rust: every mutable reference is treated as `&mut *my_mut_ref`. But it works only for exact types. So if you have any generic `` and `&mut T`, then if you try to use that mutable reference, reborrowing will not happen. – Dmitry Apr 06 '21 at 19:26