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]
}
bytes
by reaching through an immutable reference&bytes
, which the quote in your question pretty clearly says is undefined behavior. What else would you expect? – Frxstrem&AtomicU32
is derived from a&mut Bytes
.&*(&bytes as *const AtomicU32)
would be unsound even thoughbytes
itself is marked mutable, because the provenance of the pointer matters for what you can do with it. See also Temporarily opt-in to shared mutation, it's basically the same thing usingCell
but withoutunsafe
. (Unfortunately there is no stable equivalent forAtomic
s) – trentcl