Pls explain why error comes and how below code works

#![allow(warnings)]
fn main() {
   

let mut z = 4;

// 'x = { z, 8, 16}
let mut x = & mut z;

let  mut s = 444; 

// 'd = { s, 13, 24}
let mut d = &mut s;

// 'f = { d, 16, 16 } // 'f1 = { z, 8, 16}
let mut f: &mut & mut u32 = &mut x;


// 'f = { d, 20, 24 } // 'f1 = { s, 13, 24}
f = &mut d;


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 `z` as immutable because it is also borrowed as mutable
  --> src/main.rs:23:15
   |
 8 | let mut x = & mut z;
   |             ------- mutable borrow occurs here
...
23 | println!("{}",z);
   |               ^ immutable borrow occurs here
24 | 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 1 previous error

When you do both f = &mut x and f = &mut d with the same variable f, then both &mut x and &mut d must have the same lifetime.

For me it is actually a bit funny. For the original code we get a compiler error with

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!("{}", z);
    println!("{}", f);
}
   Compiling playground v0.0.1 (/playground)
warning: value assigned to `f` is never read
 --> src/main.rs:6:13
  |
6 |     let mut f: &mut &mut u32 = &mut x;
  |             ^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` on by default

error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable
 --> src/main.rs:8:20
  |
3 |     let mut x = &mut z;
  |                 ------ mutable borrow occurs here
...
8 |     println!("{}", z);
  |                    ^ immutable borrow occurs here
9 |     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`.
warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` (bin "playground") due to 1 previous error; 1 warning emitted

But when we follow the warning "warning: value assigned to f is never read"
and un-comment the assignment in line 6 it compiles successfully:

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!("{}", z);
    println!("{}", f);
}
   Compiling playground v0.0.1 (/playground)
warning: unused variable: `x`
 --> src/main.rs:3:13
  |
3 |     let mut x = &mut z;
  |             ^ help: if this is intentional, prefix it with an underscore: `_x`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: variable does not need to be mutable
 --> src/main.rs:3:9
  |
3 |     let mut x = &mut z;
  |         ----^
  |         |
  |         help: remove this `mut`
  |
  = note: `#[warn(unused_mut)]` on by default

warning: variable does not need to be mutable
 --> src/main.rs:6:9
  |
6 |     let mut f;//: &mut &mut u32 = &mut x;
  |         ----^
  |         |
  |         help: remove this `mut`

warning: `playground` (bin "playground") generated 3 warnings (run `cargo fix --bin "playground"` to apply 2 suggestions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.75s
     Running `target/debug/playground`

Standard Output

4
444

For me an interesting test for this exercise is to swap the println!s.
So we are keeping an mutable borrow alive on f that needs to be released for z to print.

This a least is my read of what the compiler is thinking.

Another way to think about it is that the current borrow checker doesn't realize that the reassignment f = &mut d can release the borrow of z in addition to that of x. I believe the next generation borrow checker (Polonius) will accept the program.

This is basically a repeat of one of your previous posts.