I can cast &mut i32 to *mut i32 in rust like so
fn main() {
let mut x = 1;
let mut xref = &mut x;
unsafe {
let xref_ptr = xref as *mut i32;
*xref_ptr = 2;
}
println!("{}", x);
}
Prints 2.
But I can't cast &mut &mut i32 to *mut *mut i32 and I don't understand why.
fn main() {
let mut x = 1;
let mut xref = &mut x;
let mut xrefref = &mut xref;
unsafe {
let xrefptr = xrefref as *mut (*mut i32);
**xrefptr = 2;
}
println!("{}", x);
}
error[E0606]: casting `&mut &mut i32` as `*mut *mut i32` is invalid
--> src/main.rs:16:23
|
16 | let xrefptr = xrefref as *mut (*mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
If references are pointers under the hood I was expecting &mut &mut i32 to be a pointer to pointer to an i32 but it appears this cast is wrong.
Why is the first cast allowed but not the second?
As @PitaJ points out, you're generally only allowed to do one cast at a time and casts aren't transitive. I.e. T as U
being valid and U as V
being valid doesn't imply that T as V
is valid.
But you can just do the cast in two steps (in safe code!):
let mut x = 1;
let mut xref = &mut x;
let mut xrefref = &mut xref;
let xrefptr = (xrefref as *mut &mut i32) as *mut *mut i32;
unsafe {
**xrefptr = 2;
}
println!("{}", x); // 2