@@ -1035,7 +1035,42 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
1035
1035
}
1036
1036
}
1037
1037
1038
- /// A newtype to construct uninitialized instances of `T`
1038
+ /// A newtype to construct uninitialized instances of `T`.
1039
+ ///
1040
+ /// The compiler, in general, assumes that variables are properly initialized
1041
+ /// at their respective type. For example, a variable of reference type must
1042
+ /// be aligned and non-NULL. This is an invariant that must *always* be upheld,
1043
+ /// even in unsafe code. As a consequence, 0-initializing a variable of reference
1044
+ /// type causes instantaneous undefined behavior, no matter whether that reference
1045
+ /// ever gets used to access memory:
1046
+ /// ```rust,no_run
1047
+ /// use std::mem;
1048
+ ///
1049
+ /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
1050
+ /// ```
1051
+ /// This is exploited by the compiler for various optimizations, such as eliding
1052
+ /// run-time checks and optimizing `enum` layout.
1053
+ ///
1054
+ /// Not initializing memory at all (instead of 0-initializing it) causes the same
1055
+ /// issue: after all, the initial value of the variable might just happen to be
1056
+ /// one that violates the invariant.
1057
+ ///
1058
+ /// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data:
1059
+ /// it is a signal to the compiler indicating that the data here might *not*
1060
+ /// be initialized:
1061
+ /// ```rust
1062
+ /// #![feature(maybe_uninit)]
1063
+ /// use std::mem::MaybeUninit;
1064
+ ///
1065
+ /// // Create an explicitly uninitialized reference.
1066
+ /// let mut x = MaybeUninit::<&i32>::uninitialized();
1067
+ /// // Set it to a valid value.
1068
+ /// x.set(&0);
1069
+ /// // Extract the initialized data -- this is only allowed *after* properly
1070
+ /// // initializing `x`!
1071
+ /// let x = unsafe { x.into_initialized() };
1072
+ /// ```
1073
+ /// The compiler then knows to not optimize this code.
1039
1074
#[ allow( missing_debug_implementations) ]
1040
1075
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1041
1076
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
@@ -1084,11 +1119,14 @@ impl<T> MaybeUninit<T> {
1084
1119
}
1085
1120
1086
1121
/// Set the value of the `MaybeUninit`. This overwrites any previous value without dropping it.
1122
+ /// For your convenience, this also returns a mutable reference to the (now
1123
+ /// safely initialized) content of `self`.
1087
1124
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1088
1125
#[ inline( always) ]
1089
- pub fn set ( & mut self , val : T ) {
1126
+ pub fn set ( & mut self , val : T ) -> & mut T {
1090
1127
unsafe {
1091
1128
self . value = ManuallyDrop :: new ( val) ;
1129
+ self . get_mut ( )
1092
1130
}
1093
1131
}
1094
1132
@@ -1102,11 +1140,19 @@ impl<T> MaybeUninit<T> {
1102
1140
/// state, otherwise this will immediately cause undefined behavior.
1103
1141
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1104
1142
#[ inline( always) ]
1105
- pub unsafe fn into_inner ( self ) -> T {
1143
+ pub unsafe fn into_initialized ( self ) -> T {
1106
1144
intrinsics:: panic_if_uninhabited :: < T > ( ) ;
1107
1145
ManuallyDrop :: into_inner ( self . value )
1108
1146
}
1109
1147
1148
+ /// Deprecated alternative to `into_initialized`. Will never get stabilized.
1149
+ /// Exists only to transition stdsimd to `into_initialized`.
1150
+ #[ inline( always) ]
1151
+ #[ allow( unused) ]
1152
+ pub ( crate ) unsafe fn into_inner ( self ) -> T {
1153
+ self . into_initialized ( )
1154
+ }
1155
+
1110
1156
/// Get a reference to the contained value.
1111
1157
///
1112
1158
/// # Unsafety
@@ -1134,16 +1180,16 @@ impl<T> MaybeUninit<T> {
1134
1180
& mut * self . value
1135
1181
}
1136
1182
1137
- /// Get a pointer to the contained value. Reading from this pointer will be undefined
1138
- /// behavior unless the `MaybeUninit` is initialized.
1183
+ /// Get a pointer to the contained value. Reading from this pointer or turning it
1184
+ /// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
1139
1185
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1140
1186
#[ inline( always) ]
1141
1187
pub fn as_ptr ( & self ) -> * const T {
1142
1188
unsafe { & * self . value as * const T }
1143
1189
}
1144
1190
1145
- /// Get a mutable pointer to the contained value. Reading from this pointer will be undefined
1146
- /// behavior unless the `MaybeUninit` is initialized.
1191
+ /// Get a mutable pointer to the contained value. Reading from this pointer or turning it
1192
+ /// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
1147
1193
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1148
1194
#[ inline( always) ]
1149
1195
pub fn as_mut_ptr ( & mut self ) -> * mut T {
0 commit comments