From 7bb5b3eb3228df648a08b02c85eddcd9b9cc85bd Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 19 Aug 2018 15:51:35 +0200 Subject: [PATCH] add MaybeUninit and deprecate mem::{uninitialized,zeroed} --- src/libcore/mem.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 1803adee3c1..91522885b59 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -514,6 +514,7 @@ pub fn needs_drop() -> bool { /// assert_eq!(0, x); /// ``` #[inline] +#[rustc_deprecated(since = "1.30.0", reason = "use `mem::MaybeUninit::zeroed` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn zeroed() -> T { intrinsics::init() @@ -608,6 +609,7 @@ pub unsafe fn zeroed() -> T { /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html #[inline] +#[rustc_deprecated(since = "1.30.0", reason = "use `mem::MaybeUninit::uninitialized` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized() -> T { intrinsics::uninit() @@ -1024,3 +1026,96 @@ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.value } } + +/// A newtype to construct uninitialized instances of `T` +#[allow(missing_debug_implementations)] +#[unstable(feature = "maybe_uninit", issue = "53491")] +pub union MaybeUninit { + uninit: (), + value: ManuallyDrop, +} + +impl MaybeUninit { + /// Create a new `MaybeUninit` in an uninitialized state. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub const fn uninitialized() -> MaybeUninit { + MaybeUninit { uninit: () } + } + + /// Create a new `MaybeUninit` in an uninitialized state, with the memory being + /// filled with `0` bytes. It depends on `T` whether that already makes for + /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, + /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not + /// be null. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub fn zeroed() -> MaybeUninit { + let mut u = MaybeUninit::::uninitialized(); + unsafe { + u.as_mut_ptr().write_bytes(0u8, 1); + } + u + } + + /// Set the value of the `MaybeUninit`. This overwrites any previous value without dropping it. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub fn set(&mut self, val: T) { + unsafe { + self.value = ManuallyDrop::new(val); + } + } + + /// Extract the value from the `MaybeUninit` container. This is a great way + /// to ensure that the data will get dropped, because the resulting `T` is + /// subject to the usual drop handling. + /// + /// # Unsafety + /// + /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized + /// state, otherwise this will immediately cause undefined behavior. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub unsafe fn into_inner(self) -> T { + ManuallyDrop::into_inner(self.value) + } + + /// Get a reference to the contained value. + /// + /// # Unsafety + /// + /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized + /// state, otherwise this will immediately cause undefined behavior. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub unsafe fn get_ref(&self) -> &T { + &*self.value + } + + /// Get a mutable reference to the contained value. + /// + /// # Unsafety + /// + /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized + /// state, otherwise this will immediately cause undefined behavior. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub unsafe fn get_mut(&mut self) -> &mut T { + &mut *self.value + } + + /// Get a pointer to the contained value. Reading from this pointer will be undefined + /// behavior unless the `MaybeUninit` is initialized. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub fn as_ptr(&self) -> *const T { + unsafe { &*self.value as *const T } + } + + /// Get a mutable pointer to the contained value. Reading from this pointer will be undefined + /// behavior unless the `MaybeUninit` is initialized. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub fn as_mut_ptr(&mut self) -> *mut T { + unsafe { &mut *self.value as *mut T } + } +} -- 2.44.0