@@ -172,7 +172,7 @@ use crate::mem::ManuallyDrop;
172
172
///
173
173
/// # Layout
174
174
///
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`:
176
176
///
177
177
/// ```rust
178
178
/// use std::mem::{MaybeUninit, size_of, align_of};
@@ -191,9 +191,23 @@ use crate::mem::ManuallyDrop;
191
191
/// assert_eq!(size_of::<Option<bool>>(), 1);
192
192
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
193
193
/// ```
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.
194
207
#[ allow( missing_debug_implementations) ]
195
208
#[ stable( feature = "maybe_uninit" , since = "1.36.0" ) ]
196
209
#[ derive( Copy ) ]
210
+ #[ cfg_attr( not( bootstrap) , repr( transparent) ) ]
197
211
pub union MaybeUninit < T > {
198
212
uninit : ( ) ,
199
213
value : ManuallyDrop < T > ,
0 commit comments