@@ -1045,17 +1045,34 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10451045/// ever gets used to access memory:
10461046///
10471047/// ```rust,no_run
1048- /// use std::mem;
1048+ /// #![feature(maybe_uninit)]
1049+ /// use std::mem::{self, MaybeUninit};
10491050///
10501051/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
1052+ /// // equivalent code with `MaybeUninit`
1053+ /// let x: &i32 = unsafe { MaybeUninit::zeroed().into_initialized() }; // undefined behavior!
10511054/// ```
10521055///
10531056/// This is exploited by the compiler for various optimizations, such as eliding
10541057/// run-time checks and optimizing `enum` layout.
10551058///
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
10571060/// 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.)
10591076///
10601077/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data:
10611078/// 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> {
10651082/// #![feature(maybe_uninit)]
10661083/// use std::mem::MaybeUninit;
10671084///
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:
10691087/// let mut x = MaybeUninit::<&i32>::uninitialized();
10701088/// // Set it to a valid value.
10711089/// x.set(&0);
@@ -1075,6 +1093,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10751093/// ```
10761094///
10771095/// The compiler then knows to not optimize this code.
1096+ // FIXME before stabilizing, explain how to initialize a struct field-by-field.
10781097#[ allow( missing_debug_implementations) ]
10791098#[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
10801099// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
@@ -1134,14 +1153,31 @@ impl<T> MaybeUninit<T> {
11341153 }
11351154 }
11361155
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+
11371172 /// Extracts the value from the `MaybeUninit` container. This is a great way
11381173 /// to ensure that the data will get dropped, because the resulting `T` is
11391174 /// subject to the usual drop handling.
11401175 ///
11411176 /// # Unsafety
11421177 ///
11431178 /// 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.
11451181 #[ unstable( feature = "maybe_uninit" , issue = "53491" ) ]
11461182 #[ inline( always) ]
11471183 pub unsafe fn into_initialized ( self ) -> T {
@@ -1162,8 +1198,9 @@ impl<T> MaybeUninit<T> {
11621198 /// # Unsafety
11631199 ///
11641200 /// 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" ) ]
11671204 #[ inline( always) ]
11681205 pub unsafe fn get_ref ( & self ) -> & T {
11691206 & * self . value
@@ -1174,41 +1211,26 @@ impl<T> MaybeUninit<T> {
11741211 /// # Unsafety
11751212 ///
11761213 /// 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.
11781216 // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
11791217 // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
11801218 // a final decision about the rules before stabilization.
1181- #[ unstable( feature = "maybe_uninit " , issue = "53491" ) ]
1219+ #[ unstable( feature = "maybe_uninit_ref " , issue = "53491" ) ]
11821220 #[ inline( always) ]
11831221 pub unsafe fn get_mut ( & mut self ) -> & mut T {
11841222 & mut * self . value
11851223 }
11861224
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-
12031225 /// 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" ) ]
12051227 #[ inline( always) ]
12061228 pub fn first_ptr ( this : & [ MaybeUninit < T > ] ) -> * const T {
12071229 this as * const [ MaybeUninit < T > ] as * const T
12081230 }
12091231
12101232 /// 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" ) ]
12121234 #[ inline( always) ]
12131235 pub fn first_ptr_mut ( this : & mut [ MaybeUninit < T > ] ) -> * mut T {
12141236 this as * mut [ MaybeUninit < T > ] as * mut T
0 commit comments