@@ -172,7 +172,7 @@ use crate::mem::ManuallyDrop;
172172///
173173/// # Layout
174174///
175- /// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
175+ /// `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as `T`:
176176///
177177/// ```rust
178178/// use std::mem::{MaybeUninit, size_of, align_of};
@@ -191,9 +191,23 @@ use crate::mem::ManuallyDrop;
191191/// assert_eq!(size_of::<Option<bool>>(), 1);
192192/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
193193/// ```
194+ ///
195+ /// If `T` is FFI-safe, then so is `MaybeUninit<T>`.
196+ ///
197+ /// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size,
198+ /// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option<T>` and
199+ /// `Option<MaybeUninit<T>>` may still have different sizes, and types containing a field of type
200+ /// `T` may be laid out (and sized) differently than if that field were `MaybeUninit<T>`.
201+ /// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the
202+ /// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact
203+ /// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not
204+ /// remain `#[repr(transparent)]`. That said, `MaybeUninit<T>` will *always* guarantee that it has
205+ /// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that
206+ /// guarantee may evolve.
194207#[ allow( missing_debug_implementations) ]
195208#[ stable( feature = "maybe_uninit" , since = "1.36.0" ) ]
196209#[ derive( Copy ) ]
210+ #[ cfg_attr( not( bootstrap) , repr( transparent) ) ]
197211pub union MaybeUninit < T > {
198212 uninit : ( ) ,
199213 value : ManuallyDrop < T > ,
0 commit comments