diff options
| author | 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> | 2024-07-22 16:44:03 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-22 16:44:03 +0800 |
| commit | 9f4039fcd5ca9027f189f525cafe367209a400bc (patch) | |
| tree | b38f61bf3a70684380f400b95a9a55773502c466 | |
| parent | b66b4020d8a34f1ac4e8566c568cff515d850bb7 (diff) | |
| parent | 351fe273547ac57ddf829b358dff538ab587599a (diff) | |
| download | rust-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.rs | 83 |
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> { |
