@@ -1045,17 +1045,34 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
1045
1045
/// ever gets used to access memory:
1046
1046
///
1047
1047
/// ```rust,no_run
1048
- /// use std::mem;
1048
+ /// #![feature(maybe_uninit)]
1049
+ /// use std::mem::{self, MaybeUninit};
1049
1050
///
1050
1051
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
1052
+ /// // equivalent code with `MaybeUninit`
1053
+ /// let x: &i32 = unsafe { MaybeUninit::zeroed().into_initialized() }; // undefined behavior!
1051
1054
/// ```
1052
1055
///
1053
1056
/// This is exploited by the compiler for various optimizations, such as eliding
1054
1057
/// run-time checks and optimizing `enum` layout.
1055
1058
///
1056
- /// Not initializing memory at all (instead of zero-- initializing it) causes the same
1059
+ /// Not initializing memory at all (instead of zero-initializing it) causes the same
1057
1060
/// issue: after all, the initial value of the variable might just happen to be
1058
- /// one that violates the invariant.
1061
+ /// one that violates the invariant. Moreover, uninitialized memory is special
1062
+ /// in that the compiler knows that it does not have a fixed value. This makes
1063
+ /// it undefined behavior to have uninitialized data in a variable even if that
1064
+ /// variable has otherwise no restrictions about which values are valid:
1065
+ ///
1066
+ /// ```rust,no_run
1067
+ /// #![feature(maybe_uninit)]
1068
+ /// use std::mem::{self, MaybeUninit};
1069
+ ///
1070
+ /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
1071
+ /// // equivalent code with `MaybeUninit`
1072
+ /// let x: i32 = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior!
1073
+ /// ```
1074
+ /// (Notice that the rules around uninitialized integers are not finalized yet, but
1075
+ /// until they are, it is advisable to avoid them.)
1059
1076
///
1060
1077
/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data:
1061
1078
/// it is a signal to the compiler indicating that the data here might *not*
@@ -1065,7 +1082,8 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
1065
1082
/// #![feature(maybe_uninit)]
1066
1083
/// use std::mem::MaybeUninit;
1067
1084
///
1068
- /// // Create an explicitly uninitialized reference.
1085
+ /// // Create an explicitly uninitialized reference. The compiler knows that data inside
1086
+ /// // a `MaybeUninit` may be invalid, and hence this is not UB:
1069
1087
/// let mut x = MaybeUninit::<&i32>::uninitialized();
1070
1088
/// // Set it to a valid value.
1071
1089
/// x.set(&0);
@@ -1075,6 +1093,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
1075
1093
/// ```
1076
1094
///
1077
1095
/// The compiler then knows to not optimize this code.
1096
+ // FIXME before stabilizing, explain how to initialize a struct field-by-field.
1078
1097
#[ allow( missing_debug_implementations) ]
1079
1098
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1080
1099
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
@@ -1134,14 +1153,31 @@ impl<T> MaybeUninit<T> {
1134
1153
}
1135
1154
}
1136
1155
1156
+ /// Gets a pointer to the contained value. Reading from this pointer or turning it
1157
+ /// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
1158
+ #[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1159
+ #[ inline( always) ]
1160
+ pub fn as_ptr ( & self ) -> * const T {
1161
+ unsafe { & * self . value as * const T }
1162
+ }
1163
+
1164
+ /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
1165
+ /// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
1166
+ #[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1167
+ #[ inline( always) ]
1168
+ pub fn as_mut_ptr ( & mut self ) -> * mut T {
1169
+ unsafe { & mut * self . value as * mut T }
1170
+ }
1171
+
1137
1172
/// Extracts the value from the `MaybeUninit` container. This is a great way
1138
1173
/// to ensure that the data will get dropped, because the resulting `T` is
1139
1174
/// subject to the usual drop handling.
1140
1175
///
1141
1176
/// # Unsafety
1142
1177
///
1143
1178
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
1144
- /// state, otherwise this will immediately cause undefined behavior.
1179
+ /// state. Calling this when the content is not yet fully initialized causes undefined
1180
+ /// behavior.
1145
1181
#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1146
1182
#[ inline( always) ]
1147
1183
pub unsafe fn into_initialized ( self ) -> T {
@@ -1162,8 +1198,9 @@ impl<T> MaybeUninit<T> {
1162
1198
/// # Unsafety
1163
1199
///
1164
1200
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
1165
- /// state, otherwise this will immediately cause undefined behavior.
1166
- #[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1201
+ /// state. Calling this when the content is not yet fully initialized causes undefined
1202
+ /// behavior.
1203
+ #[ unstable( feature = "maybe_uninit_ref" , issue = "53491" ) ]
1167
1204
#[ inline( always) ]
1168
1205
pub unsafe fn get_ref ( & self ) -> & T {
1169
1206
& * self . value
@@ -1174,41 +1211,26 @@ impl<T> MaybeUninit<T> {
1174
1211
/// # Unsafety
1175
1212
///
1176
1213
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
1177
- /// state, otherwise this will immediately cause undefined behavior.
1214
+ /// state. Calling this when the content is not yet fully initialized causes undefined
1215
+ /// behavior.
1178
1216
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
1179
1217
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
1180
1218
// a final decision about the rules before stabilization.
1181
- #[ unstable( feature = "maybe_uninit " , issue = "53491" ) ]
1219
+ #[ unstable( feature = "maybe_uninit_ref " , issue = "53491" ) ]
1182
1220
#[ inline( always) ]
1183
1221
pub unsafe fn get_mut ( & mut self ) -> & mut T {
1184
1222
& mut * self . value
1185
1223
}
1186
1224
1187
- /// Gets a pointer to the contained value. Reading from this pointer or turning it
1188
- /// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
1189
- #[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1190
- #[ inline( always) ]
1191
- pub fn as_ptr ( & self ) -> * const T {
1192
- unsafe { & * self . value as * const T }
1193
- }
1194
-
1195
- /// Get sa mutable pointer to the contained value. Reading from this pointer or turning it
1196
- /// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
1197
- #[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
1198
- #[ inline( always) ]
1199
- pub fn as_mut_ptr ( & mut self ) -> * mut T {
1200
- unsafe { & mut * self . value as * mut T }
1201
- }
1202
-
1203
1225
/// Gets a pointer to the first element of the array.
1204
- #[ unstable( feature = "maybe_uninit " , issue = "53491" ) ]
1226
+ #[ unstable( feature = "maybe_uninit_slice " , issue = "53491" ) ]
1205
1227
#[ inline( always) ]
1206
1228
pub fn first_ptr ( this : & [ MaybeUninit < T > ] ) -> * const T {
1207
1229
this as * const [ MaybeUninit < T > ] as * const T
1208
1230
}
1209
1231
1210
1232
/// Gets a mutable pointer to the first element of the array.
1211
- #[ unstable( feature = "maybe_uninit " , issue = "53491" ) ]
1233
+ #[ unstable( feature = "maybe_uninit_slice " , issue = "53491" ) ]
1212
1234
#[ inline( always) ]
1213
1235
pub fn first_ptr_mut ( this : & mut [ MaybeUninit < T > ] ) -> * mut T {
1214
1236
this as * mut [ MaybeUninit < T > ] as * mut T
0 commit comments