@@ -471,14 +471,12 @@ pub const fn needs_drop<T>() -> bool {
471471/// There is no guarantee that an all-zero byte-pattern represents a valid value of
472472/// some type `T`. For example, the all-zero byte-pattern is not a valid value
473473/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types
474- /// causes immediate [undefined behavior][ub].
475- ///
476- /// See the documentation of [`MaybeUninit<T>`] and [`MaybeUninit::zeroed()`][zeroed]
477- /// for more discussion on how to initialize values.
474+ /// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv]
475+ /// that there always is a valid value in a variable it considers initialized.
478476///
479477/// [zeroed]: union.MaybeUninit.html#method.zeroed
480- /// [`MaybeUninit<T>`]: union.MaybeUninit.html
481478/// [ub]: ../../reference/behavior-considered-undefined.html
479+ /// [inv]: union.MaybeUninit.html#initialization-invariant
482480///
483481/// # Examples
484482///
@@ -508,11 +506,21 @@ pub unsafe fn zeroed<T>() -> T {
508506/// Bypasses Rust's normal memory-initialization checks by pretending to
509507/// produce a value of type `T`, while doing nothing at all.
510508///
511- /// **This functon is deprecated because it basically cannot be used correctly.**
509+ /// **This functon is deprecated.** Use [`MaybeUninit<T>`] instead.
512510///
513- /// Use [`MaybeUninit<T>`] instead.
511+ /// The reason for deprecation is that the function basically cannot be used
512+ /// correctly: [the Rust compiler assumes][inv] that values are properly initialized.
513+ /// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate
514+ /// undefined behavior for returning a `bool` that is not definitely either `true`
515+ /// or `false`. Worse, truly uninitialized memory like what gets returned here
516+ /// is special in that the compiler knows that it does not have a fixed value.
517+ /// This makes it undefined behavior to have uninitialized data in a variable even
518+ /// if that variable has an integer type.
519+ /// (Notice that the rules around uninitialized integers are not finalized yet, but
520+ /// until they are, it is advisable to avoid them.)
514521///
515522/// [`MaybeUninit<T>`]: union.MaybeUninit.html
523+ /// [inv]: union.MaybeUninit.html#initialization-invariant
516524#[ inline]
517525#[ rustc_deprecated( since = "1.40.0" , reason = "use `mem::MaybeUninit` instead" ) ]
518526#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1022,21 +1030,23 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10221030/// use std::mem::{self, MaybeUninit};
10231031/// use std::ptr;
10241032///
1025- /// let data = unsafe {
1033+ /// let data = {
10261034/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
10271035/// // safe because the type we are claiming to have initialized here is a
10281036/// // bunch of `MaybeUninit`s, which do not require initialization.
1029- /// let mut data: [MaybeUninit<Vec<u32>>; 1000] = MaybeUninit::uninit().assume_init();
1037+ /// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
1038+ /// MaybeUninit::uninit().assume_init()
1039+ /// };
10301040///
10311041/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
10321042/// // we have a memory leak, but there is no memory safety issue.
10331043/// for elem in &mut data[..] {
1034- /// ptr::write(elem.as_mut_ptr(), vec![42]);
1044+ /// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); }
10351045/// }
10361046///
10371047/// // Everything is initialized. Transmute the array to the
10381048/// // initialized type.
1039- /// mem::transmute::<_, [Vec<u32>; 1000]>(data)
1049+ /// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
10401050/// };
10411051///
10421052/// println!("{:?}", &data[0]);
@@ -1049,29 +1059,27 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10491059/// use std::mem::MaybeUninit;
10501060/// use std::ptr;
10511061///
1052- /// unsafe {
1053- /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
1054- /// // safe because the type we are claiming to have initialized here is a
1055- /// // bunch of `MaybeUninit`s, which do not require initialization.
1056- /// let mut data: [MaybeUninit<String>; 1000] = MaybeUninit::uninit().assume_init();
1057- /// // Count the number of elements we have assigned.
1058- /// let mut data_len: usize = 0;
1062+ /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
1063+ /// // safe because the type we are claiming to have initialized here is a
1064+ /// // bunch of `MaybeUninit`s, which do not require initialization.
1065+ /// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
1066+ /// // Count the number of elements we have assigned.
1067+ /// let mut data_len: usize = 0;
10591068///
1060- /// for elem in &mut data[0..500] {
1061- /// ptr::write(elem.as_mut_ptr(), String::from("hello"));
1062- /// data_len += 1;
1063- /// }
1069+ /// for elem in &mut data[0..500] {
1070+ /// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); }
1071+ /// data_len += 1;
1072+ /// }
10641073///
1065- /// // For each item in the array, drop if we allocated it.
1066- /// for elem in &mut data[0..data_len] {
1067- /// ptr::drop_in_place(elem.as_mut_ptr());
1068- /// }
1074+ /// // For each item in the array, drop if we allocated it.
1075+ /// for elem in &mut data[0..data_len] {
1076+ /// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
10691077/// }
10701078/// ```
10711079///
10721080/// ## Initializing a struct field-by-field
10731081///
1074- /// There is unfortunately currently no supported way to create a raw pointer or reference
1082+ /// There is currently no supported way to create a raw pointer or reference
10751083/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
10761084/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
10771085/// to its fields.
@@ -1183,7 +1191,7 @@ impl<T> MaybeUninit<T> {
11831191 /// Gets a pointer to the contained value. Reading from this pointer or turning it
11841192 /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
11851193 /// Writing to memory that this pointer (non-transitively) points to is undefined behavior
1186- /// (except inside an `UnsafeCell`).
1194+ /// (except inside an `UnsafeCell<T> `).
11871195 ///
11881196 /// # Examples
11891197 ///
0 commit comments