diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2019-07-06 17:19:58 +0200 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2019-08-16 17:11:18 +0200 |
| commit | 7b02b9f8ec2850ac687ee5c7d869a626e09d22cb (patch) | |
| tree | 3c5a4f49589032d666c3b87aeca4a72bd392688c /src/liballoc | |
| parent | 1613fdae37df044f2c254d25d356b3a57eb61a50 (diff) | |
| download | rust-7b02b9f8ec2850ac687ee5c7d869a626e09d22cb.tar.gz rust-7b02b9f8ec2850ac687ee5c7d869a626e09d22cb.zip | |
Add new_uninit and assume_init on Box, Rc, and Arc
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/boxed.rs | 61 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 81 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 81 |
3 files changed, 223 insertions, 0 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c92db517cad..5ea7847ca45 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -93,6 +93,7 @@ use core::ops::{ use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; +use crate::alloc; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -121,6 +122,32 @@ impl<T> Box<T> { box x } + /// Construct a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// Box::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Box<mem::MaybeUninit<T>> { + let layout = alloc::Layout::new::<mem::MaybeUninit<T>>(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + Box(unique.cast()) + } + /// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -130,6 +157,40 @@ impl<T> Box<T> { } } +impl<T> Box<mem::MaybeUninit<T>> { + /// Convert to `Box<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::<u32>::new_uninit(); + /// + /// let five: Box<u32> = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// Box::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Box<T> { + Box(Box::into_unique(this).cast()) + } +} + impl<T: ?Sized> Box<T> { /// Constructs a box from a raw pointer. /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 22d06180d8d..c902580354d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,6 +327,43 @@ impl<T> Rc<T> { })) } + /// Construct a new Rc with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Rc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> { + let layout = Layout::new::<RcBox<mem::MaybeUninit<T>>>(); + unsafe { + let mut ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .cast::<RcBox<mem::MaybeUninit<T>>>(); + ptr::write(&mut ptr.as_mut().strong, Cell::new(1)); + ptr::write(&mut ptr.as_mut().weak, Cell::new(1)); + Rc { + ptr, + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -377,6 +414,48 @@ impl<T> Rc<T> { } } +impl<T> Rc<mem::MaybeUninit<T>> { + /// Convert to `Rc<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Rc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Rc<T> { + let ptr = this.ptr.cast(); + mem::forget(this); + Rc { + ptr, + phantom: PhantomData, + } + } +} + impl<T: ?Sized> Rc<T> { /// Consumes the `Rc`, returning the wrapped pointer. /// @@ -582,6 +661,8 @@ impl<T: ?Sized> Rc<T> { /// # Examples /// /// ``` + /// #![feature(get_mut_unchecked)] + /// /// use std::rc::Rc; /// /// let mut x = Rc::new(String::new()); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4cd8e1fd4dd..8c63c81ee27 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -311,6 +311,43 @@ impl<T> Arc<T> { Self::from_inner(Box::into_raw_non_null(x)) } + /// Construct a Arc box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Arc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> { + let layout = Layout::new::<ArcInner<mem::MaybeUninit<T>>>(); + unsafe { + let mut ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .cast::<ArcInner<mem::MaybeUninit<T>>>(); + ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1)); + Arc { + ptr, + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -361,6 +398,48 @@ impl<T> Arc<T> { } } +impl<T> Arc<mem::MaybeUninit<T>> { + /// Convert to `Arc<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Arc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Arc<T> { + let ptr = this.ptr.cast(); + mem::forget(this); + Arc { + ptr, + phantom: PhantomData, + } + } +} + impl<T: ?Sized> Arc<T> { /// Consumes the `Arc`, returning the wrapped pointer. /// @@ -967,6 +1046,8 @@ impl<T: ?Sized> Arc<T> { /// # Examples /// /// ``` + /// #![feature(get_mut_unchecked)] + /// /// use std::sync::Arc; /// /// let mut x = Arc::new(String::new()); |
