Skip to content

Commit 7dbd962

Browse files
committed
try_with_capacity for RawVec
1 parent 5ad7454 commit 7dbd962

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

library/alloc/src/raw_vec.rs

+22-15
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ impl<T> RawVec<T, Global> {
9393
/// zero-sized. Note that if `T` is zero-sized this means you will
9494
/// *not* get a `RawVec` with the requested capacity.
9595
///
96+
/// Non-fallible version of `try_with_capacity`
97+
///
9698
/// # Panics
9799
///
98100
/// Panics if the requested capacity exceeds `isize::MAX` bytes.
@@ -104,7 +106,7 @@ impl<T> RawVec<T, Global> {
104106
#[must_use]
105107
#[inline]
106108
pub fn with_capacity(capacity: usize) -> Self {
107-
Self::with_capacity_in(capacity, Global)
109+
handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global))
108110
}
109111

110112
/// Like `with_capacity`, but guarantees the buffer is zeroed.
@@ -142,15 +144,15 @@ impl<T, A: Allocator> RawVec<T, A> {
142144
#[cfg(not(no_global_oom_handling))]
143145
#[inline]
144146
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
145-
Self::allocate_in(capacity, AllocInit::Uninitialized, alloc)
147+
handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc))
146148
}
147149

148150
/// Like `with_capacity_zeroed`, but parameterized over the choice
149151
/// of allocator for the returned `RawVec`.
150152
#[cfg(not(no_global_oom_handling))]
151153
#[inline]
152154
pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
153-
Self::allocate_in(capacity, AllocInit::Zeroed, alloc)
155+
handle_reserve(Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc))
154156
}
155157

156158
/// Converts the entire buffer into `Box<[MaybeUninit<T>]>` with the specified `len`.
@@ -179,39 +181,44 @@ impl<T, A: Allocator> RawVec<T, A> {
179181
}
180182
}
181183

182-
#[cfg(not(no_global_oom_handling))]
183-
fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
184+
fn try_allocate_in(
185+
capacity: usize,
186+
init: AllocInit,
187+
alloc: A,
188+
) -> Result<Self, TryReserveError> {
184189
// Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
190+
185191
if T::IS_ZST || capacity == 0 {
186-
Self::new_in(alloc)
192+
Ok(Self::new_in(alloc))
187193
} else {
188194
// We avoid `unwrap_or_else` here because it bloats the amount of
189195
// LLVM IR generated.
190196
let layout = match Layout::array::<T>(capacity) {
191197
Ok(layout) => layout,
192-
Err(_) => capacity_overflow(),
198+
Err(_) => return Err(CapacityOverflow.into()),
193199
};
194-
match alloc_guard(layout.size()) {
195-
Ok(_) => {}
196-
Err(_) => capacity_overflow(),
200+
201+
if let Err(err) = alloc_guard(layout.size()) {
202+
return Err(err);
197203
}
204+
198205
let result = match init {
199206
AllocInit::Uninitialized => alloc.allocate(layout),
200207
AllocInit::Zeroed => alloc.allocate_zeroed(layout),
201208
};
202209
let ptr = match result {
203210
Ok(ptr) => ptr,
204-
Err(_) => handle_alloc_error(layout),
211+
Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()),
205212
};
206213

207214
// Allocators currently return a `NonNull<[u8]>` whose length
208215
// matches the size requested. If that ever changes, the capacity
209216
// here should change to `ptr.len() / mem::size_of::<T>()`.
210-
Self {
217+
Ok(Self {
211218
ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) },
212219
cap: unsafe { Cap(capacity) },
213220
alloc,
214-
}
221+
})
215222
}
216223
}
217224

@@ -536,11 +543,11 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
536543
// Central function for reserve error handling.
537544
#[cfg(not(no_global_oom_handling))]
538545
#[inline]
539-
fn handle_reserve(result: Result<(), TryReserveError>) {
546+
fn handle_reserve<T>(result: Result<T, TryReserveError>) -> T {
540547
match result.map_err(|e| e.kind()) {
548+
Ok(res) => res,
541549
Err(CapacityOverflow) => capacity_overflow(),
542550
Err(AllocError { layout, .. }) => handle_alloc_error(layout),
543-
Ok(()) => { /* yay */ }
544551
}
545552
}
546553

library/alloc/src/raw_vec/tests.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,14 @@ fn zst() {
105105
let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
106106
zst_sanity(&v);
107107

108-
let v: RawVec<ZST> = RawVec::allocate_in(0, AllocInit::Uninitialized, Global);
108+
let v: RawVec<ZST> = RawVec::try_allocate_in(0, AllocInit::Uninitialized, Global).unwrap();
109109
zst_sanity(&v);
110110

111-
let v: RawVec<ZST> = RawVec::allocate_in(100, AllocInit::Uninitialized, Global);
111+
let v: RawVec<ZST> = RawVec::try_allocate_in(100, AllocInit::Uninitialized, Global).unwrap();
112112
zst_sanity(&v);
113113

114-
let mut v: RawVec<ZST> = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global);
114+
let mut v: RawVec<ZST> =
115+
RawVec::try_allocate_in(usize::MAX, AllocInit::Uninitialized, Global).unwrap();
115116
zst_sanity(&v);
116117

117118
// Check all these operations work as expected with zero-sized elements.

0 commit comments

Comments
 (0)