Skip to content

Commit 546e45a

Browse files
japaricRalfJung
authored andcommitted
add MaybeUninit
1 parent e37d6d3 commit 546e45a

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/libcore/mem.rs

+96
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ pub fn needs_drop<T>() -> bool {
514514
/// assert_eq!(0, x);
515515
/// ```
516516
#[inline]
517+
#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::zeroed` instead")]
517518
#[stable(feature = "rust1", since = "1.0.0")]
518519
pub unsafe fn zeroed<T>() -> T {
519520
intrinsics::init()
@@ -608,6 +609,7 @@ pub unsafe fn zeroed<T>() -> T {
608609
/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
609610
/// [`Drop`]: ../ops/trait.Drop.html
610611
#[inline]
612+
#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")]
611613
#[stable(feature = "rust1", since = "1.0.0")]
612614
pub unsafe fn uninitialized<T>() -> T {
613615
intrinsics::uninit()
@@ -1024,3 +1026,97 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10241026
&mut self.value
10251027
}
10261028
}
1029+
1030+
/// A newtype to construct uninitialized instances of `T`
1031+
#[allow(missing_debug_implementations)]
1032+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1033+
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
1034+
pub union MaybeUninit<T> {
1035+
uninit: (),
1036+
value: ManuallyDrop<T>,
1037+
}
1038+
1039+
impl<T> MaybeUninit<T> {
1040+
/// Create a new `MaybeUninit` in an uninitialized state.
1041+
///
1042+
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.
1043+
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
1044+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1045+
pub const fn uninitialized() -> MaybeUninit<T> {
1046+
MaybeUninit { uninit: () }
1047+
}
1048+
1049+
/// Create a new `MaybeUninit` in an uninitialized state, with the memory being
1050+
/// filled with `0` bytes. It depends on `T` whether that already makes for
1051+
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
1052+
/// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
1053+
/// be null.
1054+
///
1055+
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.
1056+
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
1057+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1058+
pub fn zeroed() -> MaybeUninit<T> {
1059+
let mut u = MaybeUninit::<T>::uninitialized();
1060+
unsafe {
1061+
u.as_mut_ptr().write_bytes(0u8, 1);
1062+
}
1063+
u
1064+
}
1065+
1066+
/// Set the value of the `MaybeUninit`. This overwrites any previous value without dropping it.
1067+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1068+
pub fn set(&mut self, val: T) {
1069+
unsafe {
1070+
self.value = ManuallyDrop::new(val);
1071+
}
1072+
}
1073+
1074+
/// Extract the value from the `MaybeUninit` container. This is a great way
1075+
/// to ensure that the data will get dropped, because the resulting `T` is
1076+
/// subject to the usual drop handling.
1077+
///
1078+
/// # Unsafety
1079+
///
1080+
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
1081+
/// state, otherwise this will immediately cause undefined behavior.
1082+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1083+
pub unsafe fn into_inner(self) -> T {
1084+
ManuallyDrop::into_inner(self.value)
1085+
}
1086+
1087+
/// Get a reference to the contained value.
1088+
///
1089+
/// # Unsafety
1090+
///
1091+
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
1092+
/// state, otherwise this will immediately cause undefined behavior.
1093+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1094+
pub unsafe fn get_ref(&self) -> &T {
1095+
&*self.value
1096+
}
1097+
1098+
/// Get a mutable reference to the contained value.
1099+
///
1100+
/// # Unsafety
1101+
///
1102+
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
1103+
/// state, otherwise this will immediately cause undefined behavior.
1104+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1105+
pub unsafe fn get_mut(&mut self) -> &mut T {
1106+
&mut *self.value
1107+
}
1108+
1109+
/// Get a pointer to the contained value. Reading from this pointer will be undefined
1110+
/// behavior unless the `MaybeUninit` is initialized.
1111+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1112+
pub fn as_ptr(&self) -> *const T {
1113+
unsafe { &*self.value as *const T }
1114+
}
1115+
1116+
/// Get a mutable pointer to the contained value. Reading from this pointer will be undefined
1117+
/// behavior unless the `MaybeUninit` is initialized.
1118+
#[unstable(feature = "maybe_uninit", issue = "53491")]
1119+
pub fn as_mut_ptr(&mut self) -> *mut T {
1120+
unsafe { &mut *self.value as *mut T }
1121+
}
1122+
}

0 commit comments

Comments
 (0)