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
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.