In other words, pointer-integer-pointer roundtrips are not possible (in the sense that the resulting pointer is not dereferenceable).
I am curious if an embedded platform says we should write something to the address 0x0010 to make some work, how it work with rust on that platform? For example:
fn main() {
let ptr = 0x0010 as *mut u8;
unsafe {
*ptr = 1; // #1 make the beep sound
};
}
The current Rust document says that #1 can cause UB. MIRI says:
error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
However, assuming this is a practical code in that platform, how does Rust work on that platform?
error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 16 bytes of memory, but got 0xe000e010[noalloc] which is a dangling pointer (it has no provenance)
Most code needs no changes to conform to strict provenance, as the only really concerning operation that wasn’t obviously already Undefined Behaviour is casts from usize to a pointer.
In other words, pointer-integer-pointer roundtrips are not possible (in the sense that the resulting pointer is not dereferenceable).
Strict provenance is not the real ruleset of Rust. Rather, strict provenance is a set of rules that:
Is relatively easy to teach.
Is not overly restrictive, i.e. most programs can follow strict provenance without issues.
Can be emulated perfectly by interpreters such as miri.
Is more strict than the real rules.
Anything that is ok under strict provenance is also ok under the real ruleset, but the reverse is not true. There are things that are rejected by strict provenance, but ok under the real rules. Mmio access by casting an integer to pointer is one such thing.