diff options
| author | Jorge Aparicio <jorge@japaric.io> | 2018-08-19 15:51:35 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2018-09-29 09:50:51 +0200 |
| commit | 546e45ab5b20b9151b3331c727ecb5fd2e3eecaf (patch) | |
| tree | 795f2a0619d0dc5fe1715d666a6fca935d852369 | |
| parent | e37d6d37e76a8b2f82eacc8c3f642c4d47093950 (diff) | |
| download | rust-546e45ab5b20b9151b3331c727ecb5fd2e3eecaf.tar.gz rust-546e45ab5b20b9151b3331c727ecb5fd2e3eecaf.zip | |
add MaybeUninit
| -rw-r--r-- | src/libcore/mem.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 1803adee3c1..c99c9f96f12 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -514,6 +514,7 @@ pub fn needs_drop<T>() -> bool { /// assert_eq!(0, x); /// ``` #[inline] +#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::zeroed` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn zeroed<T>() -> T { intrinsics::init() @@ -608,6 +609,7 @@ pub unsafe fn zeroed<T>() -> T { /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html #[inline] +#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized<T>() -> T { intrinsics::uninit() @@ -1024,3 +1026,97 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { &mut self.value } } + +/// A newtype to construct uninitialized instances of `T` +#[allow(missing_debug_implementations)] +#[unstable(feature = "maybe_uninit", issue = "53491")] +// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}` +pub union MaybeUninit<T> { + uninit: (), + value: ManuallyDrop<T>, +} + +impl<T> MaybeUninit<T> { + /// 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<T> { + 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<usize>::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<T> { + let mut u = MaybeUninit::<T>::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 } + } +} |
