diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 0d8c3ef906bf0..6bfefabef4ceb 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -2,13 +2,15 @@ use crate::any::type_name; use crate::mem::ManuallyDrop; use crate::{fmt, intrinsics, ptr, slice}; -/// A wrapper type to construct uninitialized instances of `T`. +/// A `MaybeUninit` is like a `T`, but without the requirement that it is properly initialized as a `T`. +/// Dropping a `MaybeUninit` does nothing, even if properly initialized as a `T`, because +/// the compiler relies on the type system to decide how to drop variables. Thus, if a `MaybeUninit` +/// should be dropped like a `T`, it should be converted to a `T` with `assume_init` or similar. /// /// # Initialization invariant /// -/// The compiler, in general, assumes that a variable is properly initialized -/// according to the requirements of the variable's type. For example, a variable of -/// reference type must be aligned and non-null. This is an invariant that must +/// Every variable must be properly initialized according to the requirements of its type. +/// For example, a variable of reference type must be aligned and non-null. This is an invariant that must /// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a /// variable of reference type causes instantaneous [undefined behavior][ub], /// no matter whether that reference ever gets used to access memory: @@ -25,7 +27,7 @@ use crate::{fmt, intrinsics, ptr, slice}; /// This is exploited by the compiler for various optimizations, such as eliding /// run-time checks and optimizing `enum` layout. /// -/// Similarly, entirely uninitialized memory may have any content, while a `bool` must +/// Similarly, entirely uninitialized memory may have any value, while a `bool` must /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: /// /// ```rust,no_run @@ -37,11 +39,11 @@ use crate::{fmt, intrinsics, ptr, slice}; /// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ /// ``` /// -/// Moreover, uninitialized memory is special in that it does not have a fixed value ("fixed" -/// meaning "it won't change without being written to"). Reading the same uninitialized byte -/// multiple times can give different results. This makes it undefined behavior to have -/// uninitialized data in a variable even if that variable has an integer type, which otherwise can -/// hold any *fixed* bit pattern: +/// Moreover, uninitialized memory is special in that it does not have a fixed +/// (unchanged unless written to) value . Reading the same uninitialized byte +/// multiple times can give different results. This even makes it undefined +/// behavior to have uninitialized data in a variable of integer type, +/// which otherwise could hold any *fixed* bit pattern: /// /// ```rust,no_run /// # #![allow(invalid_value)] @@ -308,7 +310,7 @@ impl MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } } - /// Creates a new `MaybeUninit` in an uninitialized state. + /// Creates a new uninitialized `MaybeUninit`. /// /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. @@ -331,7 +333,7 @@ impl MaybeUninit { MaybeUninit { uninit: () } } - /// Creates a new array of `MaybeUninit` items, in an uninitialized state. + /// Creates a new array of uninitialized `MaybeUninit` elements. /// /// Note: in a future Rust version this method may become unnecessary /// when Rust allows @@ -367,8 +369,7 @@ impl MaybeUninit { [const { MaybeUninit::uninit() }; N] } - /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being - /// filled with `0` bytes. It depends on `T` whether that already makes for + /// Creates a new zero-filled `MaybeUninit`. It depends on `T` whether that already makes for /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not /// be null. @@ -425,16 +426,13 @@ impl MaybeUninit { /// This overwrites any previous value without dropping it, so be careful /// not to use this twice unless you want to skip running the destructor. /// For your convenience, this also returns a mutable reference to the - /// (now safely initialized) contents of `self`. + /// (now safely initialized) value of `self`. /// - /// As the content is stored inside a `MaybeUninit`, the destructor is not - /// run for the inner data if the MaybeUninit leaves scope without a call to - /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives - /// the mutable reference returned by this function needs to keep this in - /// mind. The safety model of Rust regards leaks as safe, but they are - /// usually still undesirable. This being said, the mutable reference - /// behaves like any other mutable reference would, so assigning a new value - /// to it will drop the old content. + /// Keep in mind, that the value, as it is wrapped in a `MaybeUninit`, + /// will not be dropped when its wrapper is. You can make sure the value is dropped by unwrapping + /// it with a call to [`assume_init`], or by dropping it directly with [`assume_init_drop`]. + /// While the value is also dropped when the returned mutable reference is assigned a new value, + /// the new value is then subject to the same rules, as now the new value is wrapped in a `MaybeUninit`. /// /// [`assume_init`]: Self::assume_init /// [`assume_init_drop`]: Self::assume_init_drop @@ -470,7 +468,7 @@ impl MaybeUninit { /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. /// # unsafe { MaybeUninit::assume_init_drop(&mut x); } - /// // This leaks the contained string: + /// // This leaks the initialized string: /// x.write("hello".to_string()); /// // x is initialized now: /// let s = unsafe { x.assume_init() }; @@ -513,7 +511,7 @@ impl MaybeUninit { unsafe { self.assume_init_mut() } } - /// Gets a pointer to the contained value. Reading from this pointer or turning it + /// Gets a pointer to the `T` value of the `MaybeUninit`. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. /// Writing to memory that this pointer (non-transitively) points to is undefined behavior /// (except inside an `UnsafeCell`). @@ -545,7 +543,7 @@ impl MaybeUninit { /// ``` /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) + /// until they are, it is advisable to avoid references to uninitialized data.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] #[rustc_as_ptr] @@ -555,7 +553,7 @@ impl MaybeUninit { self as *const _ as *const T } - /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it + /// Gets a mutable pointer to the `T` value of the `MaybeUninit`. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. /// /// # Examples @@ -597,16 +595,17 @@ impl MaybeUninit { self as *mut _ as *mut T } - /// Extracts the value from the `MaybeUninit` container. This is a great way + /// Converts an initialized `MaybeUninit` into a `T`. This is a great way /// to ensure that the data will get dropped, because the resulting `T` is /// subject to the usual drop handling. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes immediate undefined - /// behavior. The [type-level documentation][inv] contains more information about - /// this initialization invariant. + /// It is up to the caller to ensure that the `MaybeUninit` has been fully initialized, + /// before converting it into a `T`. Calling this when the `T` value of the `MaybeUninit` + /// is not yet fully initialized causes immediate undefined behavior. + /// + /// The [type-level documentation][inv] contains more information about this initialization invariant. /// /// [inv]: #initialization-invariant /// @@ -656,21 +655,23 @@ impl MaybeUninit { } } - /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject - /// to the usual drop handling. + /// Reads the `T` value of the `MaybeUninit`. The result is an ordinary `T` which, + /// just like all `T` values, is subject to the usual drop handling. /// /// Whenever possible, it is preferable to use [`assume_init`] instead, which - /// prevents duplicating the content of the `MaybeUninit`. + /// prevents duplicating the value of the `MaybeUninit`. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. The [type-level documentation][inv] contains more information about + /// It is up to the caller to ensure that the `MaybeUninit` has been fully initialized, + /// before reading the `T` value of the `MaybeUninit`. Calling this when the `T` value + /// of the `MaybeUninit` is not yet fully initialized causes immediate undefined behavior. + /// + /// The [type-level documentation][inv] contains more information about /// this initialization invariant. /// /// Moreover, similar to the [`ptr::read`] function, this function creates a - /// bitwise copy of the contents, regardless whether the contained type + /// bitwise copy of the value, regardless of whether its type /// implements the [`Copy`] trait or not. When using multiple copies of the /// data (by calling `assume_init_read` multiple times, or first calling /// `assume_init_read` and then [`assume_init`]), it is your responsibility @@ -726,16 +727,16 @@ impl MaybeUninit { } } - /// Drops the contained value in place. + /// Drops the `T` value of the `MaybeUninit` in place. /// /// If you have ownership of the `MaybeUninit`, you can also use /// [`assume_init`] as an alternative. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is - /// in an initialized state. Calling this when the content is not yet fully - /// initialized causes undefined behavior. + /// It is up to the caller to ensure that the `MaybeUninit` has been fully initialized, + /// before dropping the `T` value of the `MaybeUninit`. Calling this when the `T` value + /// of the `MaybeUninit` is not yet fully initialized causes immediate undefined behavior. /// /// On top of that, all additional invariants of the type `T` must be /// satisfied, as the `Drop` implementation of `T` (or its members) may @@ -755,7 +756,7 @@ impl MaybeUninit { unsafe { ptr::drop_in_place(self.as_mut_ptr()) } } - /// Gets a shared reference to the contained value. + /// Gets a shared reference to the `T` value of the `MaybeUninit`. /// /// This can be useful when we want to access a `MaybeUninit` that has been /// initialized but don't have ownership of the `MaybeUninit` (preventing the use @@ -763,9 +764,9 @@ impl MaybeUninit { /// /// # Safety /// - /// Calling this when the content is not yet fully initialized causes undefined - /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really - /// is in an initialized state. + /// It is up to the caller to ensure that the `MaybeUninit` has been fully initialized, + /// before getting a reference to the `T` value of the `MaybeUninit`. Calling this when the `T` value + /// of the `MaybeUninit` is not yet fully initialized causes immediate undefined behavior. /// /// # Examples /// @@ -823,7 +824,7 @@ impl MaybeUninit { } } - /// Gets a mutable (unique) reference to the contained value. + /// Gets a mutable (unique) reference to the `T` value of the `MaybeUninit`. /// /// This can be useful when we want to access a `MaybeUninit` that has been /// initialized but don't have ownership of the `MaybeUninit` (preventing the use @@ -831,10 +832,9 @@ impl MaybeUninit { /// /// # Safety /// - /// Calling this when the content is not yet fully initialized causes undefined - /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really - /// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to - /// initialize a `MaybeUninit`. + /// It is up to the caller to ensure that the `MaybeUninit` has been fully initialized, + /// before getting a mutable reference to the `T` value of the `MaybeUninit`. Calling this when the `T` value + /// of the `MaybeUninit` is not yet fully initialized causes immediate undefined behavior. /// /// # Examples /// @@ -940,12 +940,12 @@ impl MaybeUninit { } } - /// Extracts the values from an array of `MaybeUninit` containers. + /// Extracts the values from an array of `MaybeUninit` wrappers. /// /// # Safety /// /// It is up to the caller to guarantee that all elements of the array are - /// in an initialized state. + /// properly initialized. /// /// # Examples /// @@ -980,10 +980,9 @@ impl MaybeUninit { } } - /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. + /// Returns a slice of potentially uninitialized bytes to the value of this `MaybeUninit`. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized. /// /// # Examples /// @@ -1005,11 +1004,9 @@ impl MaybeUninit { } } - /// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized - /// bytes. + /// Returns a mutable slice of potentially uninitialized bytes to the value of this `MaybeUninit`. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized. /// /// # Examples /// @@ -1103,8 +1100,9 @@ impl MaybeUninit { this.write_clone_of_slice(src) } - /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now - /// initialized contents of the slice. + /// Fills a `&mut [MaybeUninit]` with clones of the given value of type `T`. + /// Returns a `&mut [T]` to the so initialized slice. + /// /// Any previously initialized elements will not be dropped. /// /// This is similar to [`slice::fill`]. @@ -1282,8 +1280,8 @@ impl MaybeUninit { } impl [MaybeUninit] { - /// Copies the elements from `src` to `self`, - /// returning a mutable reference to the now initialized contents of `self`. + /// Copies all elements from a `&[T]` to this `[MaybeUninit]`. + /// Returns a `&mut [T]` to the so initialized array. /// /// If `T` does not implement `Copy`, use [`write_clone_of_slice`] instead. /// @@ -1340,13 +1338,14 @@ impl [MaybeUninit] { unsafe { self.assume_init_mut() } } - /// Clones the elements from `src` to `self`, - /// returning a mutable reference to the now initialized contents of `self`. + /// Clones all elements from a `&[T]` to this `[MaybeUninit]`. + /// Returns a `&mut [T]` to the so initialized array. /// Any already initialized elements will not be dropped. /// /// If `T` implements `Copy`, use [`write_copy_of_slice`] instead. /// - /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements. + /// This is similar to [`slice::clone_from_slice`] but cannot drop existing `MaybeUninit`, + /// as it cannot know if any of them was initialized. /// /// # Panics /// @@ -1419,10 +1418,9 @@ impl [MaybeUninit] { unsafe { self.assume_init_mut() } } - /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. + /// Returns a slice of potentially uninitialized bytes to the value of this `[MaybeUninit]`. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized. /// /// # Examples /// @@ -1445,11 +1443,9 @@ impl [MaybeUninit] { } } - /// Returns the contents of this `MaybeUninit` slice as a mutable slice of potentially - /// uninitialized bytes. + /// Returns a mutable slice of potentially uninitialized bytes to the value of this `[MaybeUninit]`. /// - /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still - /// contain padding bytes which are left uninitialized. + /// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized. /// /// # Examples /// @@ -1478,13 +1474,13 @@ impl [MaybeUninit] { } } - /// Drops the contained values in place. + /// Assumes all elements have been fully initialized and drops them in place. /// /// # Safety /// - /// It is up to the caller to guarantee that every `MaybeUninit` in the slice - /// really is in an initialized state. Calling this when the content is not yet - /// fully initialized causes undefined behavior. + /// It is up to the caller to ensure that the `MaybeUninit` has been fully initialized, + /// before calling. Calling this when any of the `T` elements of the `[MaybeUninit]` + /// has not yet been fully initialized causes immediate undefined behavior. /// /// On top of that, all additional invariants of the type `T` must be /// satisfied, as the `Drop` implementation of `T` (or its members) may @@ -1505,13 +1501,13 @@ impl [MaybeUninit] { } } - /// Gets a shared reference to the contained value. + /// Gets a `&[T]` to the values in the `&[MaybeUninit]`. /// /// # Safety /// - /// Calling this when the content is not yet fully initialized causes undefined + /// Calling this when the elements have not been fully initialized causes undefined /// behavior: it is up to the caller to guarantee that every `MaybeUninit` in - /// the slice really is in an initialized state. + /// the slice really is properly initialized. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub const unsafe fn assume_init_ref(&self) -> &[T] { @@ -1522,13 +1518,13 @@ impl [MaybeUninit] { unsafe { &*(self as *const Self as *const [T]) } } - /// Gets a mutable (unique) reference to the contained value. + /// Gets a `&mut [T]` to the values in the `&mut [MaybeUninit]`. /// /// # Safety /// - /// Calling this when the content is not yet fully initialized causes undefined + /// Calling this when the elements have not been fully initialized causes undefined /// behavior: it is up to the caller to guarantee that every `MaybeUninit` in the - /// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot + /// slice really is properly initialized. For instance, `.assume_init_mut()` cannot /// be used to initialize a `MaybeUninit` slice. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)]