@@ -471,14 +471,12 @@ pub const fn needs_drop<T>() -> bool {
471
471
/// There is no guarantee that an all-zero byte-pattern represents a valid value of
472
472
/// some type `T`. For example, the all-zero byte-pattern is not a valid value
473
473
/// 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.
478
476
///
479
477
/// [zeroed]: union.MaybeUninit.html#method.zeroed
480
- /// [`MaybeUninit<T>`]: union.MaybeUninit.html
481
478
/// [ub]: ../../reference/behavior-considered-undefined.html
479
+ /// [inv]: union.MaybeUninit.html#initialization-invariant
482
480
///
483
481
/// # Examples
484
482
///
@@ -508,11 +506,21 @@ pub unsafe fn zeroed<T>() -> T {
508
506
/// Bypasses Rust's normal memory-initialization checks by pretending to
509
507
/// produce a value of type `T`, while doing nothing at all.
510
508
///
511
- /// **This functon is deprecated because it basically cannot be used correctly.**
509
+ /// **This functon is deprecated.** Use [`MaybeUninit<T>`] instead.
512
510
///
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.)
514
521
///
515
522
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
523
+ /// [inv]: union.MaybeUninit.html#initialization-invariant
516
524
#[ inline]
517
525
#[ rustc_deprecated( since = "1.40.0" , reason = "use `mem::MaybeUninit` instead" ) ]
518
526
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1022,21 +1030,23 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
1022
1030
/// use std::mem::{self, MaybeUninit};
1023
1031
/// use std::ptr;
1024
1032
///
1025
- /// let data = unsafe {
1033
+ /// let data = {
1026
1034
/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
1027
1035
/// // safe because the type we are claiming to have initialized here is a
1028
1036
/// // 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
+ /// };
1030
1040
///
1031
1041
/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
1032
1042
/// // we have a memory leak, but there is no memory safety issue.
1033
1043
/// for elem in &mut data[..] {
1034
- /// ptr::write(elem.as_mut_ptr(), vec![42]);
1044
+ /// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); }
1035
1045
/// }
1036
1046
///
1037
1047
/// // Everything is initialized. Transmute the array to the
1038
1048
/// // initialized type.
1039
- /// mem::transmute::<_, [Vec<u32>; 1000]>(data)
1049
+ /// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
1040
1050
/// };
1041
1051
///
1042
1052
/// println!("{:?}", &data[0]);
@@ -1049,29 +1059,27 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
1049
1059
/// use std::mem::MaybeUninit;
1050
1060
/// use std::ptr;
1051
1061
///
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;
1059
1068
///
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
+ /// }
1064
1073
///
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()); }
1069
1077
/// }
1070
1078
/// ```
1071
1079
///
1072
1080
/// ## Initializing a struct field-by-field
1073
1081
///
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
1075
1083
/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
1076
1084
/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
1077
1085
/// to its fields.
@@ -1183,7 +1191,7 @@ impl<T> MaybeUninit<T> {
1183
1191
/// Gets a pointer to the contained value. Reading from this pointer or turning it
1184
1192
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
1185
1193
/// Writing to memory that this pointer (non-transitively) points to is undefined behavior
1186
- /// (except inside an `UnsafeCell`).
1194
+ /// (except inside an `UnsafeCell<T> `).
1187
1195
///
1188
1196
/// # Examples
1189
1197
///
0 commit comments