Consider the following program:
fn main() {
use core::ptr::*;
unsafe { dbg!(replace(null_mut(), ())); }
}
This was made a legal program in Rust 1.80, the preconditions state:
dst must be valid for both reads and writes.
dst must be properly aligned.
dst must point to a properly initialized value of type T.
This is because in Rust 1.80 the following line was added to valid:
For operations of size zero, every pointer is valid, including the null pointer. The following points are only concerned with non-zero-sized accesses.
Nevertheless, running the above program results in undefined behavior:
error: Undefined Behavior: constructing invalid value: encountered a null reference
--> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1227:22
|
1227 | mem::replace(&mut *dst, src)
| ^^^^^^^^^ constructing invalid value: encountered a null reference
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::ptr::replace::<()>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1227:22: 1227:31
note: inside `main`
--> src/main.rs:3:19
|
3 | unsafe { dbg!(replace(null_mut(), ())); }
| ^^^^^^^^^^^^^^^^^^^^^^^
Rather than changing the implementation of core::ptr::replace, or an isolated change to the requirements of core::ptr::replace, I would like to see the change to the definition of a valid pointer for ZSTs reverted, I've expanded more about my thoughts and provided more arguments in this T-opsem zulip thread. In short, I believe that unsoundness similar to the case here in core::ptr::replace will keep happening as long as "dereferencing a pointer" and "reborrowing a pointer" have different requirements (which they do since Rust 1.80).
Consider the following program:
This was made a legal program in Rust 1.80, the preconditions state:
dstmust be valid for both reads and writes.dstmust be properly aligned.dstmust point to a properly initialized value of typeT.This is because in Rust 1.80 the following line was added to valid:
Nevertheless, running the above program results in undefined behavior:
Rather than changing the implementation of
core::ptr::replace, or an isolated change to the requirements ofcore::ptr::replace, I would like to see the change to the definition of a valid pointer for ZSTs reverted, I've expanded more about my thoughts and provided more arguments in this T-opsem zulip thread. In short, I believe that unsoundness similar to the case here incore::ptr::replacewill keep happening as long as "dereferencing a pointer" and "reborrowing a pointer" have different requirements (which they do since Rust 1.80).