diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index d0be82adb6b16..d25f4297dbb84 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -252,6 +252,44 @@ use crate::{fmt, intrinsics, ptr, slice}; /// std::process::exit(*code); // UB! Accessing uninitialized memory. /// } /// ``` +/// +/// # Validity +/// +/// A `MaybeUninit` has no validity requirement – any sequence of bytes of the appropriate length, +/// initialized to any value or uninitialized, are a valid value of `MaybeUninit`. Equivalently, +/// it is always sound to perform `transmute::<[MaybeUninit; size_of::()], MaybeUninit>(...)`. +/// +/// Note that "round-tripping" via `MaybeUninit` does not always result in the original value. +/// Concretely, given distinct `T` and `U` where `size_of::() == size_of::()`, the following +/// code is not guaranteed to be sound: +/// +/// ```rust,no_run +/// # use core::mem::{MaybeUninit, transmute}; +/// # struct T; struct U; +/// fn identity(t: T) -> T { +/// unsafe { +/// let u: MaybeUninit = transmute(t); +/// transmute(u) +/// } +/// } +/// ``` +/// +/// If `T` contains initialized bytes at byte offsets where `U` contains padding bytes, these +/// may not be preserved in `MaybeUninit`, and so `transmute(u)` may produce a `T` with +/// uninitialized bytes in these positions. This is an active area of discussion, and this code +/// may become sound in the future. +/// +/// Note that, so long as every byte position which is initialized in `T` is also initialized +/// in `U`, then the preceding `identity` example *is* sound. +/// +/// # Provenance +/// +/// `MaybeUninit` values may contain [pointer provenance][provenance]. Concretely, for any +/// pointer type, `P`, which contains provenance, transmuting `p: P` to +/// `MaybeUninit<[u8; size_of::

]>` and then back to `P` will produce a value identical to +/// `p`, including provenance. +/// +/// [provenance]: ../ptr/index.html#provenance #[stable(feature = "maybe_uninit", since = "1.36.0")] // Lang item so we can wrap other types in it. This is useful for coroutines. #[lang = "maybe_uninit"]