about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2024-07-22 16:44:03 +0800
committerGitHub <noreply@github.com>2024-07-22 16:44:03 +0800
commit9f4039fcd5ca9027f189f525cafe367209a400bc (patch)
treeb38f61bf3a70684380f400b95a9a55773502c466
parentb66b4020d8a34f1ac4e8566c568cff515d850bb7 (diff)
parent351fe273547ac57ddf829b358dff538ab587599a (diff)
downloadrust-9f4039fcd5ca9027f189f525cafe367209a400bc.tar.gz
rust-9f4039fcd5ca9027f189f525cafe367209a400bc.zip
Rollup merge of #127415 - AljoschaMeyer:master, r=dtolnay
Add missing try_new_uninit_slice_in and try_new_zeroed_slice_in

The methods for fallible slice allocation in a given allocator were missing from `Box`, which was an oversight according to https://github.com/rust-lang/wg-allocators/issues/130

This PR adds them as `try_new_uninit_slice_in` and `try_new_zeroed_slice_in`. I simply copy-pasted the implementations of `try_new_uninit_slice` and `try_new_zeroed_slice` and adusted doc comment, typings, and the allocator it uses internally.

Also adds missing punctuation to the doc comments of `try_new_uninit_slice` and `try_new_zeroed_slice`.

Related issue is https://github.com/rust-lang/rust/issues/32838 (Allocator traits and std::heap) *I think*. Also relevant is https://github.com/rust-lang/rust/issues/63291, but I did not add the corresponding `#[unstable]` proc macro, since `try_new_uninit_slice` and `try_new_zeroed_slice` are also not annotated with it.
-rw-r--r--library/alloc/src/boxed.rs83
1 files changed, 81 insertions, 2 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index f299aa0124d..405430377e5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -704,7 +704,7 @@ impl<T> Box<[T]> {
     }
 
     /// Constructs a new boxed slice with uninitialized contents. Returns an error if
-    /// the allocation fails
+    /// the allocation fails.
     ///
     /// # Examples
     ///
@@ -739,7 +739,7 @@ impl<T> Box<[T]> {
     }
 
     /// Constructs a new boxed slice with uninitialized contents, with the memory
-    /// being filled with `0` bytes. Returns an error if the allocation fails
+    /// being filled with `0` bytes. Returns an error if the allocation fails.
     ///
     /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
     /// of this method.
@@ -831,6 +831,85 @@ impl<T, A: Allocator> Box<[T], A> {
     pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
         unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) }
     }
+
+    /// Constructs a new boxed slice with uninitialized contents in the provided allocator. Returns an error if
+    /// the allocation fails.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let mut values = Box::<[u32], _>::try_new_uninit_slice_in(3, System)?;
+    /// let values = unsafe {
+    ///     // Deferred initialization:
+    ///     values[0].as_mut_ptr().write(1);
+    ///     values[1].as_mut_ptr().write(2);
+    ///     values[2].as_mut_ptr().write(3);
+    ///     values.assume_init()
+    /// };
+    ///
+    /// assert_eq!(*values, [1, 2, 3]);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new_uninit_slice_in(
+        len: usize,
+        alloc: A,
+    ) -> Result<Box<[mem::MaybeUninit<T>], A>, AllocError> {
+        let ptr = if T::IS_ZST || len == 0 {
+            NonNull::dangling()
+        } else {
+            let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
+                Ok(l) => l,
+                Err(_) => return Err(AllocError),
+            };
+            alloc.allocate(layout)?.cast()
+        };
+        unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) }
+    }
+
+    /// Constructs a new boxed slice with uninitialized contents in the provided allocator, with the memory
+    /// being filled with `0` bytes. Returns an error if the allocation fails.
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let values = Box::<[u32], _>::try_new_zeroed_slice_in(3, System)?;
+    /// let values = unsafe { values.assume_init() };
+    ///
+    /// assert_eq!(*values, [0, 0, 0]);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new_zeroed_slice_in(
+        len: usize,
+        alloc: A,
+    ) -> Result<Box<[mem::MaybeUninit<T>], A>, AllocError> {
+        let ptr = if T::IS_ZST || len == 0 {
+            NonNull::dangling()
+        } else {
+            let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
+                Ok(l) => l,
+                Err(_) => return Err(AllocError),
+            };
+            alloc.allocate_zeroed(layout)?.cast()
+        };
+        unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) }
+    }
 }
 
 impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {