diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 030f4f1d12cc8..1bfb852424d63 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -100,6 +100,7 @@ #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] +#![cfg_attr(not(bootstrap), feature(transparent_unions))] #![feature(unboxed_closures)] #![feature(unsized_locals)] #![feature(untagged_unions)] diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index eeff9d0303a3b..28e1e22ba7ff2 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -172,7 +172,7 @@ use crate::mem::ManuallyDrop; /// /// # Layout /// -/// `MaybeUninit` is guaranteed to have the same size and alignment as `T`: +/// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as `T`: /// /// ```rust /// use std::mem::{MaybeUninit, size_of, align_of}; @@ -191,9 +191,23 @@ use crate::mem::ManuallyDrop; /// assert_eq!(size_of::>(), 1); /// assert_eq!(size_of::>>(), 2); /// ``` +/// +/// If `T` is FFI-safe, then so is `MaybeUninit`. +/// +/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, +/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option` and +/// `Option>` may still have different sizes, and types containing a field of type +/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit`. +/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the +/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact +/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not +/// remain `#[repr(transparent)]`. That said, `MaybeUninit` will *always* guarantee that it has +/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that +/// guarantee may evolve. #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] #[derive(Copy)] +#[cfg_attr(not(bootstrap), repr(transparent))] pub union MaybeUninit { uninit: (), value: ManuallyDrop,