Skip to content

Commit dd2c6c3

Browse files
committed
Add fallible box APIs (Box::try_new_*)
1 parent d116f48 commit dd2c6c3

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

library/alloc/src/boxed.rs

+73-1
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,77 @@ impl<T> Box<T> {
241241
pub fn pin(x: T) -> Pin<Box<T>> {
242242
(box x).into()
243243
}
244+
245+
/// Allocates memory on the heap then places `x` into it,
246+
/// returning an error if the allocation fails
247+
///
248+
/// This doesn't actually allocate if `T` is zero-sized.
249+
///
250+
/// # Examples
251+
///
252+
/// ```
253+
/// #![feature(allocator_api)]
254+
///
255+
/// let five = Box::try_new(5)?;
256+
/// # Ok::<(), std::alloc::AllocError>(())
257+
/// ```
258+
#[unstable(feature = "allocator_api", issue = "32838")]
259+
#[inline]
260+
pub fn try_new(x: T) -> Result<Self, AllocError> {
261+
Self::try_new_in(x, Global)
262+
}
263+
264+
/// Constructs a new box with uninitialized contents on the heap,
265+
/// returning an error if the allocation fails
266+
///
267+
/// # Examples
268+
///
269+
/// ```
270+
/// #![feature(allocator_api, new_uninit)]
271+
///
272+
///
273+
/// let mut five = Box::<u32>::try_new_uninit()?;
274+
///
275+
/// let five = unsafe {
276+
/// // Deferred initialization:
277+
/// five.as_mut_ptr().write(5);
278+
///
279+
/// five.assume_init()
280+
/// };
281+
///
282+
/// assert_eq!(*five, 5);
283+
/// # Ok::<(), std::alloc::AllocError>(())
284+
/// ```
285+
#[unstable(feature = "allocator_api", issue = "32838")]
286+
// #[unstable(feature = "new_uninit", issue = "63291")]
287+
pub fn try_new_uninit() -> Result<Box<mem::MaybeUninit<T>>, AllocError> {
288+
Box::try_new_uninit_in(Global)
289+
}
290+
291+
/// Constructs a new `Box` with uninitialized contents, with the memory
292+
/// being filled with `0` bytes on the heap
293+
///
294+
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
295+
/// of this method.
296+
///
297+
/// # Examples
298+
///
299+
/// ```
300+
/// #![feature(allocator_api, new_uninit)]
301+
///
302+
/// let zero = Box::<u32>::try_new_zeroed()?;
303+
/// let zero = unsafe { zero.assume_init() };
304+
///
305+
/// assert_eq!(*zero, 0);
306+
/// # Ok::<(), std::alloc::AllocError>(())
307+
/// ```
308+
///
309+
/// [zeroed]: mem::MaybeUninit::zeroed
310+
#[unstable(feature = "allocator_api", issue = "32838")]
311+
// #[unstable(feature = "new_uninit", issue = "63291")]
312+
pub fn try_new_zeroed() -> Result<Box<mem::MaybeUninit<T>>, AllocError> {
313+
Box::try_new_zeroed_in(Global)
314+
}
244315
}
245316

246317
impl<T, A: Allocator> Box<T, A> {
@@ -380,7 +451,8 @@ impl<T, A: Allocator> Box<T, A> {
380451
}
381452

382453
/// Constructs a new `Box` with uninitialized contents, with the memory
383-
/// being filled with `0` bytes in the provided allocator.
454+
/// being filled with `0` bytes in the provided allocator,
455+
/// returning an error if the allocation fails,
384456
///
385457
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
386458
/// of this method.

library/alloc/src/rc.rs

+22
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,28 @@ impl<T> Rc<T> {
346346
)
347347
}
348348

349+
/// Constructs a new `Rc<T>`.
350+
///
351+
/// # Examples
352+
///
353+
/// ```
354+
/// #![feature(allocator_api, new_uninit)]
355+
/// use std::rc::Rc;
356+
///
357+
/// let five = Rc::new(5);
358+
/// ```
359+
#[stable(feature = "rust1", since = "1.0.0")]
360+
pub fn try_new(value: T) -> Result<Rc<T>, AllocError> {
361+
// There is an implicit weak pointer owned by all the strong
362+
// pointers, which ensures that the weak destructor never frees
363+
// the allocation while the strong destructor is running, even
364+
// if the weak pointer is stored inside the strong one.
365+
Ok(Self::from_inner(
366+
Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
367+
.into(),
368+
))
369+
}
370+
349371
/// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
350372
/// to upgrade the weak reference before this function returns will result
351373
/// in a `None` value. However, the weak reference may be cloned freely and

0 commit comments

Comments
 (0)