Pls explain why & how this program didn't compile

#![allow(warnings)]
fn main() {
    let mut z = 4;
    let mut x = &mut z;

    let mut s = 444;
    let mut d = &mut s;

    let mut f: &mut &mut u32 = &mut x;

    f = &mut d;

    println!("{}", f);

    let mut zz = 4444;
    x = &mut zz;

    println!("{}", zz);
    println!("{}", z);
    println!("{}", f);
}

fn ok<'s>(arg1: &'s mut &mut u32, arg2: &'s mut u32) {}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `zz` as immutable because it is also borrowed as mutable
  --> src/main.rs:18:20
   |
16 |     x = &mut zz;
   |         ------- mutable borrow occurs here
17 |
18 |     println!("{}", zz);
   |                    ^^ immutable borrow occurs here
19 |     println!("{}", z);
20 |     println!("{}", f);
   |                    - mutable borrow later used here
   |
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable
  --> src/main.rs:19:20
   |
4  |     let mut x = &mut z;
   |                 ------ mutable borrow occurs here
...
19 |     println!("{}", z);
   |                    ^ immutable borrow occurs here
20 |     println!("{}", f);
   |                    - mutable borrow later used here
   |
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground` (bin "playground") due to 2 previous errors

Hi!

First, please use cargo fmt (on the playground, use the Rustfmt tool) to format the code so that it is easier to read.

To answer your question, reduce the code to the minimal example that reproduces the error:

fn main() {
    let mut z = 4;
    let f = &mut z;

    println!("{z}");
    println!("{f}");
}

This code is "interleaving" mutable and shared references (a violation of the Aliasing XOR Mutable discipline that Rust enforces) by holding a mutable reference (f = &mut z) across a shared reference &z.

It's kind of hard to see the shared reference because it is hidden inside the println!() macro.

The error goes away when println!("{f}"); is removed because the mutable reference then gets dropped before the shared reference &z gets used in println!("{z}");

3 Likes

In &mut T the T is invariant. So even when f = &mut d; gets called; the borrow of z remains enforced (until the end of fs life.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.