Rust proposal explores freeze loads for uninitialized memory semantics
A proposed `read_freeze` API would let unsafe Rust read uninitialized memory as an arbitrary bit pattern instead of UB, which could clarify some low-level code and expose others to new traps.

A proposal to add `core::ptr::read_freeze<T>(ptr: *const T) -> T` goes right at the nerve center of unsafe Rust. The pitch is simple enough to state and tricky enough to matter: let a load from uninitialized memory produce an arbitrary bit pattern instead of undefined behavior, while still requiring the pointer to be valid and the resulting bits to form a valid `T`.
What `read_freeze` is trying to guarantee
`core::ptr::read()` already assumes the pointed-to value is initialized, so using it on a half-built object can blow up the language model even if the hardware happily returns bytes. `read_freeze` would change the contract: you still cannot point it at junk, and you still cannot use it to conjure an invalid `T`, but you would get a defined result for the uninitialized case instead of invoking UB.
That makes the proposal tightly tied to type validity. It fits cleanly for types where every bit pattern is acceptable, and it gets much narrower for values like `bool`, `char`, references, and many enums, where some bit patterns are not legal Rust values. In practice, that means the idea is less about “reading anything anywhere” and more about making a specific class of low-level loads behave predictably.
Why uninitialized memory keeps coming back
Rust has been circling this problem for years because it sits between safety and optimization. A 2016 Rust Internals thread on uninitialized memory spelled out the baseline guarantees of safe Rust, data-race freedom, memory safety, and type safety, then asked what should happen when code reads from an uninitialized but allocated slice of scalars. Such code could be memory-safe and type-safe in one sense while still carrying security risk in another.
A 2017 Rust Internals thread sharpened the rule of thumb: types can be read safely from arbitrary memory only when all bit patterns are valid values. That is the boundary `read_freeze` is trying to make explicit.
Ralf Jung’s 2019 blog post, “What The Hardware Does is not what your Program Does: Uninitialized Memory,” pushed back on the instinct to reason from raw machine behavior.
LLVM is the reason this is a semantics fight, not just an API idea
LLVM’s `undef` and `poison` semantics, discussed in the Rust Internals thread “Taming Undefined Behavior in LLVM” and a PLDI paper it cited, can snowball into contradictory optimization assumptions. Once the compiler decides a value is impossible or unstable in the wrong way, the resulting miscompilation can spread far beyond the original load.
A freeze-like operation tries to pin an indeterminate value to one arbitrary concrete bit pattern so the optimizer can keep moving without turning the whole path into UB.
The concrete code paths that make this real
The 2025 Rust Internals discussion about a safe abstraction over uninitialized memory gave a very practical example: a Fibonacci-array setup where the compiler does unnecessary work to zero the array. If you are allocating a buffer only to overwrite every slot before anyone reads it, extra zeroing is pure overhead, but if you try to dodge it with the wrong unsafe pattern, you can step into UB.
A reply in that same discussion pointed to an LZ decoder that processes bytes in a 16-byte SIMD register before writing them out. That kind of code pushes people toward raw pointers and `MaybeUninit`, because the algorithm may load ahead of the final write. The open question is whether that load is a legitimate masked read from a larger machine word or an out-of-bounds read dressed up as performance work.
Another reply in the 2025 thread warned that if `freeze` happens to yield the right byte, it could expose a side-channel attack.
Where `MaybeUninit` fits today
The standard library already gives you `MaybeUninit`, a wrapper type for constructing uninitialized instances of `T`. That is the current escape hatch when you need to build an object piece by piece without paying for an initial write you plan to overwrite anyway. It is also the tool that keeps the burden on you to know exactly when the bytes become a real value.
A 2022 Rust Internals thread on exposing `freeze(MaybeUninit<T>) -> MaybeUninit<T>` for masked reads tied the pieces together: the author wanted LLVM’s `freeze` semantics surfaced at the Rust level and drew a line between that and freezing arbitrarily sized regions of memory. The proposal is not trying to replace `MaybeUninit`; it is trying to give unsafe authors a sharper primitive for the cases where a load has to happen before full initialization is complete.
This article was produced by Prism’s automated news system from verified source data, official records, and press releases, then run through automated quality and moderation checks before publishing. The system is built and supervised by the people who set the standards it runs under. Read our full AI policy.
Did this article answer your question?


