The best way to resolve this would be to run the code example under MIRI, which you can do from a web browser using the Playground.
This is the output I get from running it (miri is in the Tools menu):
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.91s
Running `/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/playground`
error: Undefined Behavior: attempting a read access using <3121> at alloc1664[0x0], but that tag does not exist in the borrow stack for this location
--> src/main.rs:8:5
|
8 | *y += 1;
| ^^^^^^^
| |
| attempting a read access using <3121> at alloc1664[0x0], but that tag does not exist in the borrow stack for this location
| this error occurs as part of an access at alloc1664[0x0..0x4]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <3121> was created by a Unique retag at offsets [0x0..0x4]
--> src/main.rs:4:22
|
4 | let y = unsafe { &mut *ptr };
| ^^^^^^^^^
help: <3121> was later invalidated at offsets [0x0..0x4] by a SharedReadOnly retag
--> src/main.rs:5:13
|
5 | let z = &x;
| ^^
= note: BACKTRACE (of the first span):
= note: inside `main` at src/main.rs:8:5: 8:12
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error
Be warned that Miri has false negatives, so using it doesn't constitue proof of soundness. If Miri says it's UB then it's UB, but if Miri says it's OK, then it might still be UB.
Technically, if Miri says it's UB, it may turn out ok. It even warns in some cases that its rules are not final. But in this simple case it's definitely UB.
Even more importantly, miri will only detect UB that’s actually encountered, whereas “soundness” is concerned with all UB that could possibly be encountered by using potentially hard to find corner-case inputs to the function/API in question.
Furthermore, certain kinds of (almost-)UB tend to not manifest at all, for example a program incorrectly relying on the layout of structs (without an explicit repr(C) or repr(transparent)).[1]