Skip to content

Commit d116f48

Browse files
committed
Add fallible box allocator APIs (Box::try_new_*_in())
1 parent 353f3a3 commit d116f48

File tree

1 file changed

+85
-1
lines changed

1 file changed

+85
-1
lines changed

library/alloc/src/boxed.rs

+85-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ use core::pin::Pin;
153153
use core::ptr::{self, Unique};
154154
use core::task::{Context, Poll};
155155

156-
use crate::alloc::{handle_alloc_error, Allocator, Global, Layout};
156+
use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout};
157157
use crate::borrow::Cow;
158158
use crate::raw_vec::RawVec;
159159
use crate::str::from_boxed_utf8_unchecked;
@@ -267,6 +267,31 @@ impl<T, A: Allocator> Box<T, A> {
267267
}
268268
}
269269

270+
/// Allocates memory in the given allocator then places `x` into it,
271+
/// returning an error if the allocation fails
272+
///
273+
/// This doesn't actually allocate if `T` is zero-sized.
274+
///
275+
/// # Examples
276+
///
277+
/// ```
278+
/// #![feature(allocator_api)]
279+
///
280+
/// use std::alloc::System;
281+
///
282+
/// let five = Box::try_new_in(5, System)?;
283+
/// # Ok::<(), std::alloc::AllocError>(())
284+
/// ```
285+
#[unstable(feature = "allocator_api", issue = "32838")]
286+
#[inline]
287+
pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
288+
let mut boxed = Self::try_new_uninit_in(alloc)?;
289+
unsafe {
290+
boxed.as_mut_ptr().write(x);
291+
Ok(boxed.assume_init())
292+
}
293+
}
294+
270295
/// Constructs a new box with uninitialized contents in the provided allocator.
271296
///
272297
/// # Examples
@@ -295,6 +320,36 @@ impl<T, A: Allocator> Box<T, A> {
295320
unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) }
296321
}
297322

323+
/// Constructs a new box with uninitialized contents in the provided allocator,
324+
/// returning an error if the allocation fails
325+
///
326+
/// # Examples
327+
///
328+
/// ```
329+
/// #![feature(allocator_api, new_uninit)]
330+
///
331+
/// use std::alloc::System;
332+
///
333+
/// let mut five = Box::<u32, _>::try_new_uninit_in(System)?;
334+
///
335+
/// let five = unsafe {
336+
/// // Deferred initialization:
337+
/// five.as_mut_ptr().write(5);
338+
///
339+
/// five.assume_init()
340+
/// };
341+
///
342+
/// assert_eq!(*five, 5);
343+
/// # Ok::<(), std::alloc::AllocError>(())
344+
/// ```
345+
#[unstable(feature = "allocator_api", issue = "32838")]
346+
// #[unstable(feature = "new_uninit", issue = "63291")]
347+
pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
348+
let layout = Layout::new::<mem::MaybeUninit<T>>();
349+
let ptr = alloc.allocate(layout)?.cast();
350+
unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
351+
}
352+
298353
/// Constructs a new `Box` with uninitialized contents, with the memory
299354
/// being filled with `0` bytes in the provided allocator.
300355
///
@@ -324,6 +379,35 @@ impl<T, A: Allocator> Box<T, A> {
324379
unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) }
325380
}
326381

382+
/// Constructs a new `Box` with uninitialized contents, with the memory
383+
/// being filled with `0` bytes in the provided allocator.
384+
///
385+
/// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
386+
/// of this method.
387+
///
388+
/// # Examples
389+
///
390+
/// ```
391+
/// #![feature(allocator_api, new_uninit)]
392+
///
393+
/// use std::alloc::System;
394+
///
395+
/// let zero = Box::<u32, _>::try_new_zeroed_in(System)?;
396+
/// let zero = unsafe { zero.assume_init() };
397+
///
398+
/// assert_eq!(*zero, 0);
399+
/// # Ok::<(), std::alloc::AllocError>(())
400+
/// ```
401+
///
402+
/// [zeroed]: mem::MaybeUninit::zeroed
403+
#[unstable(feature = "allocator_api", issue = "32838")]
404+
// #[unstable(feature = "new_uninit", issue = "63291")]
405+
pub fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
406+
let layout = Layout::new::<mem::MaybeUninit<T>>();
407+
let ptr = alloc.allocate_zeroed(layout)?.cast();
408+
unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
409+
}
410+
327411
/// Constructs a new `Pin<Box<T, A>>`. If `T` does not implement `Unpin`, then
328412
/// `x` will be pinned in memory and unable to be moved.
329413
#[unstable(feature = "allocator_api", issue = "32838")]

0 commit comments

Comments
 (0)