The Rust Reference seems to say that mutating an immutable local data (that's not inside an UnsafeCell) is undefined behavior:
Behavior considered undefined
- Mutating immutable data. All data inside a const item is immutable. Moreover, all data reached through a shared reference or data owned by an immutable binding is immutable, unless that data is contained within an
UnsafeCell<U>.
The following code mutates an immutable local variable by reinterpreting it as an AtomicU32. Currently the code runs just fine and prints the expected result, but is its behavior actually undefined?
use std::sync::atomic::{AtomicU32, Ordering};
#[repr(C, align(4))]
struct Bytes([u8; 4]);
fn main() {
let bytes = Bytes([11; 4]);
let x = unsafe { &*(&bytes as *const Bytes as *const AtomicU32) };
x.store(12345, Ordering::SeqCst);
println!("{:?}", bytes.0); // [57, 48, 0, 0]
}
Miri doesn't complain about the code example below where the bytes are mutable. Since those bytes are being mutated through a shared reference (&AtomicU32), it seems to me that according to The Rust Reference the code below should also have undefined behavior - given that "all data reached through a shared reference [..] is immutable" and "mutating immutable data [is considered undefined behavior]".
use std::sync::atomic::{AtomicU32, Ordering};
#[repr(C, align(4))]
struct Bytes([u8; 4]);
fn main() {
let mut bytes = Bytes([11; 4]);
let x = unsafe { &*(&mut bytes as *mut Bytes as *const AtomicU32) };
x.store(12345, Ordering::SeqCst);
println!("{:?}", bytes.0); // [57, 48, 0, 0]
}