diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-12-31 06:40:17 +0000 |
|---|---|---|
| committer | Manish Goregaokar <manishsmail@gmail.com> | 2020-12-31 08:14:38 +0000 |
| commit | dd2c6c318bfe3191e936f4500d60b5089db1ef60 (patch) | |
| tree | b09d512b2f9b56a15a4328b1f00e47377a28a4ed | |
| parent | d116f48788645f2b5ff5cd409f4ac8ba84f906ad (diff) | |
| download | rust-dd2c6c318bfe3191e936f4500d60b5089db1ef60.tar.gz rust-dd2c6c318bfe3191e936f4500d60b5089db1ef60.zip | |
Add fallible box APIs (`Box::try_new_*`)
| -rw-r--r-- | library/alloc/src/boxed.rs | 74 | ||||
| -rw-r--r-- | library/alloc/src/rc.rs | 22 |
2 files changed, 95 insertions, 1 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bc56c7a3c4f..eb00d1a8b47 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -241,6 +241,77 @@ impl<T> Box<T> { pub fn pin(x: T) -> Pin<Box<T>> { (box x).into() } + + /// Allocates memory on the heap then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let five = Box::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(x: T) -> Result<Self, AllocError> { + Self::try_new_in(x, Global) + } + + /// Constructs a new box with uninitialized contents on the heap, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// + /// let mut five = Box::<u32>::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result<Box<mem::MaybeUninit<T>>, AllocError> { + Box::try_new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes on the heap + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// let zero = Box::<u32>::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result<Box<mem::MaybeUninit<T>>, AllocError> { + Box::try_new_zeroed_in(Global) + } } impl<T, A: Allocator> Box<T, A> { @@ -380,7 +451,8 @@ impl<T, A: Allocator> Box<T, A> { } /// Constructs a new `Box` with uninitialized contents, with the memory - /// being filled with `0` bytes in the provided allocator. + /// being filled with `0` bytes in the provided allocator, + /// returning an error if the allocation fails, /// /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage /// of this method. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index a96be57143d..739ffd31f60 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -346,6 +346,28 @@ impl<T> Rc<T> { ) } + /// Constructs a new `Rc<T>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn try_new(value: T) -> Result<Rc<T>, AllocError> { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + Ok(Self::from_inner( + Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) + .into(), + )) + } + /// Constructs a new `Rc<T>` using a weak reference to itself. Attempting /// to upgrade the weak reference before this function returns will result /// in a `None` value. However, the weak reference may be cloned freely and |
