Skip to content

Commit 6079eee

Browse files
committed
Clarify MaybeUninit docs
1 parent 38bc246 commit 6079eee

File tree

1 file changed

+58
-59
lines changed

1 file changed

+58
-59
lines changed

library/core/src/mem/maybe_uninit.rs

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ use crate::{fmt, intrinsics, ptr, slice};
55

66
/// A wrapper type to construct uninitialized instances of `T`.
77
///
8+
/// A `MaybeUninit<T>` is like a `T`, but without the requirement that it is properly initialized as a `T`.
9+
/// Dropping a `MaybeUninit<T>` does nothing, even if properly initialized as a `T`, because
10+
/// the compiler relies on the type system to decide how to drop variables. Thus, if a `MaybeUninit<T>`
11+
/// should be dropped like a `T`, it should be converted to a `T` with `assume_init` or similar.
12+
///
813
/// # Initialization invariant
914
///
10-
/// The compiler, in general, assumes that a variable is properly initialized
11-
/// according to the requirements of the variable's type. For example, a variable of
12-
/// reference type must be aligned and non-null. This is an invariant that must
15+
/// Every variable must be properly initialized according to the requirements of its type.
16+
/// For example, a variable of reference type must be aligned and non-null. This is an invariant that must
1317
/// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a
1418
/// variable of reference type causes instantaneous [undefined behavior][ub],
1519
/// no matter whether that reference ever gets used to access memory:
@@ -392,7 +396,7 @@ impl<T> MaybeUninit<T> {
392396
MaybeUninit { value: ManuallyDrop::new(val) }
393397
}
394398

395-
/// Creates a new `MaybeUninit<T>` in an uninitialized state.
399+
/// Creates a new uninitialized `MaybeUninit<T>`.
396400
///
397401
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
398402
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
@@ -415,8 +419,7 @@ impl<T> MaybeUninit<T> {
415419
MaybeUninit { uninit: () }
416420
}
417421

418-
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
419-
/// filled with `0` bytes. It depends on `T` whether that already makes for
422+
/// Creates a new zero-filled `MaybeUninit<T>`. It depends on `T` whether that already makes for
420423
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
421424
/// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
422425
/// be null.
@@ -475,14 +478,11 @@ impl<T> MaybeUninit<T> {
475478
/// For your convenience, this also returns a mutable reference to the
476479
/// (now safely initialized) contents of `self`.
477480
///
478-
/// As the content is stored inside a `ManuallyDrop`, the destructor is not
479-
/// run for the inner data if the MaybeUninit leaves scope without a call to
480-
/// [`assume_init`], [`assume_init_drop`], or similar. Code that receives
481-
/// the mutable reference returned by this function needs to keep this in
482-
/// mind. The safety model of Rust regards leaks as safe, but they are
483-
/// usually still undesirable. This being said, the mutable reference
484-
/// behaves like any other mutable reference would, so assigning a new value
485-
/// to it will drop the old content.
481+
/// Keep in mind, that the value, as it is wrapped in a `MaybeUninit`,
482+
/// will not be dropped when its wrapper is. You can make sure the value is dropped by unwrapping
483+
/// it with a call to [`assume_init`], or by dropping it directly with [`assume_init_drop`].
484+
/// While the value is also dropped when the returned mutable reference is assigned a new value,
485+
/// the new value is then subject to the same rules, as now the new value is wrapped in a `MaybeUninit`.
486486
///
487487
/// [`assume_init`]: Self::assume_init
488488
/// [`assume_init_drop`]: Self::assume_init_drop
@@ -518,7 +518,7 @@ impl<T> MaybeUninit<T> {
518518
/// # // FIXME(https://github.com/rust-lang/miri/issues/3670):
519519
/// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak.
520520
/// # unsafe { MaybeUninit::assume_init_drop(&mut x); }
521-
/// // This leaks the contained string:
521+
/// // This leaks the initialized string:
522522
/// x.write("hello".to_string());
523523
/// // x is initialized now:
524524
/// let s = unsafe { x.assume_init() };
@@ -593,7 +593,7 @@ impl<T> MaybeUninit<T> {
593593
/// ```
594594
///
595595
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
596-
/// until they are, it is advisable to avoid them.)
596+
/// until they are, it is advisable to avoid references to uninitialized data.)
597597
#[stable(feature = "maybe_uninit", since = "1.36.0")]
598598
#[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")]
599599
#[rustc_as_ptr]
@@ -645,16 +645,17 @@ impl<T> MaybeUninit<T> {
645645
self as *mut _ as *mut T
646646
}
647647

648-
/// Extracts the value from the `MaybeUninit<T>` container. This is a great way
648+
/// Converts an initialized `MaybeUninit<T>` into a `T`. This is a great way
649649
/// to ensure that the data will get dropped, because the resulting `T` is
650650
/// subject to the usual drop handling.
651651
///
652652
/// # Safety
653653
///
654-
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
655-
/// state. Calling this when the content is not yet fully initialized causes immediate undefined
656-
/// behavior. The [type-level documentation][inv] contains more information about
657-
/// this initialization invariant.
654+
/// It is up to the caller to ensure that the `MaybeUninit<T>` has been fully initialized,
655+
/// before converting it into a `T`. Calling this when the `T` value of the `MaybeUninit<T>`
656+
/// is not yet fully initialized causes immediate undefined behavior.
657+
///
658+
/// The [type-level documentation][inv] contains more information about this initialization invariant.
658659
///
659660
/// [inv]: #initialization-invariant
660661
///
@@ -706,17 +707,19 @@ impl<T> MaybeUninit<T> {
706707
}
707708
}
708709

709-
/// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
710-
/// to the usual drop handling.
710+
/// Reads the `T` value of the `MaybeUninit<T>`. The result is an ordinary `T` which,
711+
/// just like all `T` values, is subject to the usual drop handling.
711712
///
712713
/// Whenever possible, it is preferable to use [`assume_init`] instead, which
713714
/// prevents duplicating the content of the `MaybeUninit<T>`.
714715
///
715716
/// # Safety
716717
///
717-
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
718-
/// state. Calling this when the content is not yet fully initialized causes undefined
719-
/// behavior. The [type-level documentation][inv] contains more information about
718+
/// It is up to the caller to ensure that the `MaybeUninit<T>` has been fully initialized,
719+
/// before reading the `T` value of the `MaybeUninit<T>`. Calling this when the `T` value
720+
/// of the `MaybeUninit<T>` is not yet fully initialized causes immediate undefined behavior.
721+
///
722+
/// The [type-level documentation][inv] contains more information about
720723
/// this initialization invariant.
721724
///
722725
/// Moreover, similar to the [`ptr::read`] function, this function creates a
@@ -776,16 +779,16 @@ impl<T> MaybeUninit<T> {
776779
}
777780
}
778781

779-
/// Drops the contained value in place.
782+
/// Drops the `T` value of the `MaybeUninit<T>` in place, like [`ptr::drop_in_place`].
780783
///
781784
/// If you have ownership of the `MaybeUninit`, you can also use
782785
/// [`assume_init`] as an alternative.
783786
///
784787
/// # Safety
785788
///
786-
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is
787-
/// in an initialized state. Calling this when the content is not yet fully
788-
/// initialized causes undefined behavior.
789+
/// It is up to the caller to ensure that the `MaybeUninit<T>` has been fully initialized,
790+
/// before dropping the `T` value of the `MaybeUninit<T>`. Calling this when the `T` value
791+
/// of the `MaybeUninit<T>` is not yet fully initialized causes immediate undefined behavior.
789792
///
790793
/// On top of that, all additional invariants of the type `T` must be
791794
/// satisfied, as the `Drop` implementation of `T` (or its members) may
@@ -817,9 +820,9 @@ impl<T> MaybeUninit<T> {
817820
///
818821
/// # Safety
819822
///
820-
/// Calling this when the content is not yet fully initialized causes undefined
821-
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
822-
/// is in an initialized state.
823+
/// It is up to the caller to ensure that the `MaybeUninit<T>` has been fully initialized,
824+
/// before getting a reference to the `T` value of the `MaybeUninit<T>`. Calling this when the `T` value
825+
/// of the `MaybeUninit<T>` is not yet fully initialized causes immediate undefined behavior.
823826
///
824827
/// # Examples
825828
///
@@ -884,10 +887,9 @@ impl<T> MaybeUninit<T> {
884887
///
885888
/// # Safety
886889
///
887-
/// Calling this when the content is not yet fully initialized causes undefined
888-
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
889-
/// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to
890-
/// initialize a `MaybeUninit`.
890+
/// It is up to the caller to ensure that the `MaybeUninit<T>` has been fully initialized,
891+
/// before getting a mutable reference to the `T` value of the `MaybeUninit<T>`. Calling this when the `T` value
892+
/// of the `MaybeUninit<T>` is not yet fully initialized causes immediate undefined behavior.
891893
///
892894
/// # Examples
893895
///
@@ -998,7 +1000,7 @@ impl<T> MaybeUninit<T> {
9981000
/// # Safety
9991001
///
10001002
/// It is up to the caller to guarantee that all elements of the array are
1001-
/// in an initialized state.
1003+
/// properly initialized.
10021004
///
10031005
/// # Examples
10041006
///
@@ -1035,8 +1037,7 @@ impl<T> MaybeUninit<T> {
10351037

10361038
/// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
10371039
///
1038-
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
1039-
/// contain padding bytes which are left uninitialized.
1040+
/// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized.
10401041
///
10411042
/// # Examples
10421043
///
@@ -1061,8 +1062,7 @@ impl<T> MaybeUninit<T> {
10611062
/// Returns the contents of this `MaybeUninit` as a mutable slice of potentially uninitialized
10621063
/// bytes.
10631064
///
1064-
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
1065-
/// contain padding bytes which are left uninitialized.
1065+
/// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized.
10661066
///
10671067
/// # Examples
10681068
///
@@ -1108,8 +1108,8 @@ impl<T> MaybeUninit<T> {
11081108
}
11091109

11101110
impl<T> [MaybeUninit<T>] {
1111-
/// Copies the elements from `src` to `self`,
1112-
/// returning a mutable reference to the now initialized contents of `self`.
1111+
/// Copies all elements from a `&[T]` to this `[MaybeUninit<T>]`.
1112+
/// Returns a `&mut [T]` to the so initialized array.
11131113
///
11141114
/// If `T` does not implement `Copy`, use [`write_clone_of_slice`] instead.
11151115
///
@@ -1165,13 +1165,14 @@ impl<T> [MaybeUninit<T>] {
11651165
unsafe { self.assume_init_mut() }
11661166
}
11671167

1168-
/// Clones the elements from `src` to `self`,
1169-
/// returning a mutable reference to the now initialized contents of `self`.
1168+
/// Clones all elements from a `&[T]` to this `[MaybeUninit<T>]`.
1169+
/// Returns a `&mut [T]` to the so initialized array.
11701170
/// Any already initialized elements will not be dropped.
11711171
///
11721172
/// If `T` implements `Copy`, use [`write_copy_of_slice`] instead.
11731173
///
1174-
/// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
1174+
/// This is similar to [`slice::clone_from_slice`] but cannot drop existing `MaybeUninit<T>`,
1175+
/// as it cannot know if any of them was initialized.
11751176
///
11761177
/// # Panics
11771178
///
@@ -1403,8 +1404,7 @@ impl<T> [MaybeUninit<T>] {
14031404

14041405
/// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
14051406
///
1406-
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
1407-
/// contain padding bytes which are left uninitialized.
1407+
/// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized.
14081408
///
14091409
/// # Examples
14101410
///
@@ -1430,8 +1430,7 @@ impl<T> [MaybeUninit<T>] {
14301430
/// Returns the contents of this `MaybeUninit` slice as a mutable slice of potentially
14311431
/// uninitialized bytes.
14321432
///
1433-
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
1434-
/// contain padding bytes which are left uninitialized.
1433+
/// Note that a value may still contain uninitialized padding bytes even if it has been fully initialized.
14351434
///
14361435
/// # Examples
14371436
///
@@ -1460,13 +1459,13 @@ impl<T> [MaybeUninit<T>] {
14601459
}
14611460
}
14621461

1463-
/// Drops the contained values in place.
1462+
/// Assumes all elements have been fully initialized and drops them in place, like [`ptr::drop_in_place`].
14641463
///
14651464
/// # Safety
14661465
///
1467-
/// It is up to the caller to guarantee that every `MaybeUninit<T>` in the slice
1468-
/// really is in an initialized state. Calling this when the content is not yet
1469-
/// fully initialized causes undefined behavior.
1466+
/// It is up to the caller to ensure that the `MaybeUninit<T>` has been fully initialized,
1467+
/// before calling. Calling this when any of the `T` elements of the `[MaybeUninit<T>]`
1468+
/// has not yet been fully initialized causes immediate undefined behavior.
14701469
///
14711470
/// On top of that, all additional invariants of the type `T` must be
14721471
/// satisfied, as the `Drop` implementation of `T` (or its members) may
@@ -1495,9 +1494,9 @@ impl<T> [MaybeUninit<T>] {
14951494
///
14961495
/// # Safety
14971496
///
1498-
/// Calling this when the content is not yet fully initialized causes undefined
1497+
/// Calling this when the elements have not been fully initialized causes undefined
14991498
/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in
1500-
/// the slice really is in an initialized state.
1499+
/// the slice really is properly initialized.
15011500
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
15021501
#[inline(always)]
15031502
pub const unsafe fn assume_init_ref(&self) -> &[T] {
@@ -1512,9 +1511,9 @@ impl<T> [MaybeUninit<T>] {
15121511
///
15131512
/// # Safety
15141513
///
1515-
/// Calling this when the content is not yet fully initialized causes undefined
1514+
/// Calling this when the elements have not been fully initialized causes undefined
15161515
/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the
1517-
/// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot
1516+
/// slice really is properly initialized. For instance, `.assume_init_mut()` cannot
15181517
/// be used to initialize a `MaybeUninit` slice.
15191518
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
15201519
#[inline(always)]

0 commit comments

Comments
 (0)