Skip to content

Commit 0b7af26

Browse files
committed
Auto merge of #58129 - RalfJung:maybe-uninit, r=cramertj
MaybeUninit: some docs, rename into_inner -> into_initialized, return &mut from set
2 parents c3d2490 + 4833074 commit 0b7af26

File tree

6 files changed

+65
-16
lines changed

6 files changed

+65
-16
lines changed

src/libcore/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -555,12 +555,12 @@ macro_rules! unimplemented {
555555
#[macro_export]
556556
#[unstable(feature = "maybe_uninit", issue = "53491")]
557557
macro_rules! uninitialized_array {
558-
// This `into_inner` is safe because an array of `MaybeUninit` does not
558+
// This `into_initialized` is safe because an array of `MaybeUninit` does not
559559
// require initialization.
560560
// FIXME(#49147): Could be replaced by an array initializer, once those can
561561
// be any const expression.
562562
($t:ty; $size:expr) => (unsafe {
563-
MaybeUninit::<[MaybeUninit<$t>; $size]>::uninitialized().into_inner()
563+
MaybeUninit::<[MaybeUninit<$t>; $size]>::uninitialized().into_initialized()
564564
});
565565
}
566566

src/libcore/mem.rs

+53-7
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,42 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10351035
}
10361036
}
10371037

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.
10391074
#[allow(missing_debug_implementations)]
10401075
#[unstable(feature = "maybe_uninit", issue = "53491")]
10411076
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
@@ -1084,11 +1119,14 @@ impl<T> MaybeUninit<T> {
10841119
}
10851120

10861121
/// 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`.
10871124
#[unstable(feature = "maybe_uninit", issue = "53491")]
10881125
#[inline(always)]
1089-
pub fn set(&mut self, val: T) {
1126+
pub fn set(&mut self, val: T) -> &mut T {
10901127
unsafe {
10911128
self.value = ManuallyDrop::new(val);
1129+
self.get_mut()
10921130
}
10931131
}
10941132

@@ -1102,11 +1140,19 @@ impl<T> MaybeUninit<T> {
11021140
/// state, otherwise this will immediately cause undefined behavior.
11031141
#[unstable(feature = "maybe_uninit", issue = "53491")]
11041142
#[inline(always)]
1105-
pub unsafe fn into_inner(self) -> T {
1143+
pub unsafe fn into_initialized(self) -> T {
11061144
intrinsics::panic_if_uninhabited::<T>();
11071145
ManuallyDrop::into_inner(self.value)
11081146
}
11091147

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+
11101156
/// Get a reference to the contained value.
11111157
///
11121158
/// # Unsafety
@@ -1134,16 +1180,16 @@ impl<T> MaybeUninit<T> {
11341180
&mut *self.value
11351181
}
11361182

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.
11391185
#[unstable(feature = "maybe_uninit", issue = "53491")]
11401186
#[inline(always)]
11411187
pub fn as_ptr(&self) -> *const T {
11421188
unsafe { &*self.value as *const T }
11431189
}
11441190

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.
11471193
#[unstable(feature = "maybe_uninit", issue = "53491")]
11481194
#[inline(always)]
11491195
pub fn as_mut_ptr(&mut self) -> *mut T {

src/libcore/ptr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
573573
pub unsafe fn read<T>(src: *const T) -> T {
574574
let mut tmp = MaybeUninit::<T>::uninitialized();
575575
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
576-
tmp.into_inner()
576+
tmp.into_initialized()
577577
}
578578

579579
/// Reads the value from `src` without moving it. This leaves the
@@ -642,7 +642,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
642642
copy_nonoverlapping(src as *const u8,
643643
tmp.as_mut_ptr() as *mut u8,
644644
mem::size_of::<T>());
645-
tmp.into_inner()
645+
tmp.into_initialized()
646646
}
647647

648648
/// Overwrites a memory location with the given value without reading or

src/libstd/sys/sgx/ext/arch.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32>
4141
);
4242

4343
match error {
44-
0 => Ok(out.into_inner()),
44+
0 => Ok(out.into_initialized()),
4545
err => Err(err),
4646
}
4747
}
@@ -69,6 +69,6 @@ pub fn ereport(
6969
"{rdx}"(report.as_mut_ptr())
7070
);
7171

72-
report.into_inner()
72+
report.into_initialized()
7373
}
7474
}

src/test/codegen/box-maybe-uninit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ use std::mem::MaybeUninit;
99
pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
1010
// CHECK-LABEL: @box_uninitialized
1111
// CHECK-NOT: store
12+
// CHECK-NOT: alloca
13+
// CHECK-NOT: memcpy
14+
// CHECK-NOT: memset
1215
Box::new(MaybeUninit::uninitialized())
1316
}

src/test/run-pass/panic-uninitialized-zeroed.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn main() {
3636

3737
assert_eq!(
3838
panic::catch_unwind(|| {
39-
mem::MaybeUninit::<!>::uninitialized().into_inner()
39+
mem::MaybeUninit::<!>::uninitialized().into_initialized()
4040
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
4141
s == "Attempted to instantiate uninhabited type !"
4242
})),
@@ -63,7 +63,7 @@ fn main() {
6363

6464
assert_eq!(
6565
panic::catch_unwind(|| {
66-
mem::MaybeUninit::<Foo>::uninitialized().into_inner()
66+
mem::MaybeUninit::<Foo>::uninitialized().into_initialized()
6767
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
6868
s == "Attempted to instantiate uninhabited type Foo"
6969
})),
@@ -90,7 +90,7 @@ fn main() {
9090

9191
assert_eq!(
9292
panic::catch_unwind(|| {
93-
mem::MaybeUninit::<Bar>::uninitialized().into_inner()
93+
mem::MaybeUninit::<Bar>::uninitialized().into_initialized()
9494
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
9595
s == "Attempted to instantiate uninhabited type Bar"
9696
})),

0 commit comments

Comments
 (0)