Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove helper-methods from Alloc trait and add associated Err type. #60771

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/liballoc/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {

#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl Alloc for Global {
type Err = AllocErr;

#[inline]
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
NonNull::new(alloc(layout)).ok_or(AllocErr)
Expand Down
8 changes: 4 additions & 4 deletions src/liballoc/collections/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,24 @@ use crate::alloc::{AllocErr, LayoutErr};
/// Augments `AllocErr` with a CapacityOverflow variant.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub enum CollectionAllocErr {
pub enum CollectionAllocErr<E = AllocErr> {
/// Error due to the computed capacity exceeding the collection's maximum
/// (usually `isize::MAX` bytes).
CapacityOverflow,
/// Error due to the allocator (see the `AllocErr` type's docs).
AllocErr,
AllocErr(E),
}

#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
impl From<AllocErr> for CollectionAllocErr {
#[inline]
fn from(AllocErr: AllocErr) -> Self {
CollectionAllocErr::AllocErr
CollectionAllocErr::AllocErr(AllocErr)
}
}

#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
impl From<LayoutErr> for CollectionAllocErr {
impl<E> From<LayoutErr> for CollectionAllocErr<E> {
#[inline]
fn from(_: LayoutErr) -> Self {
CollectionAllocErr::CapacityOverflow
Expand Down
37 changes: 19 additions & 18 deletions src/liballoc/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl<T, A: Alloc> RawVec<T, A> {
let elem_size = mem::size_of::<T>();

let alloc_size = cap.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
alloc_guard::<A::Err>(alloc_size).unwrap_or_else(|_| capacity_overflow());

// handles ZSTs and `cap = 0` alike
let ptr = if alloc_size == 0 {
Expand Down Expand Up @@ -305,7 +305,7 @@ impl<T, A: Alloc> RawVec<T, A> {
// `from_size_align_unchecked`.
let new_cap = 2 * self.cap;
let new_size = new_cap * elem_size;
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
alloc_guard::<A::Err>(new_size).unwrap_or_else(|_| capacity_overflow());
let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(),
cur,
new_size);
Expand All @@ -320,9 +320,12 @@ impl<T, A: Alloc> RawVec<T, A> {
// skip to 4 because tiny Vec's are dumb; but not if that
// would cause overflow
let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
match self.a.alloc_array::<T>(new_cap) {
Ok(ptr) => (new_cap, ptr.into()),
Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()),
let layout = Layout::array::<T>(new_cap)
.expect("unable to create array layout");

match self.a.alloc(layout) {
Ok(ptr) => (new_cap, ptr.cast().into()),
Err(_) => handle_alloc_error(layout),
}
}
};
Expand Down Expand Up @@ -366,7 +369,7 @@ impl<T, A: Alloc> RawVec<T, A> {
// overflow and the alignment is sufficiently small.
let new_cap = 2 * self.cap;
let new_size = new_cap * elem_size;
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
alloc_guard::<A::Err>(new_size).unwrap_or_else(|_| capacity_overflow());
match self.a.grow_in_place(NonNull::from(self.ptr).cast(), old_layout, new_size) {
Ok(_) => {
// We can't directly divide `size`.
Expand All @@ -382,7 +385,7 @@ impl<T, A: Alloc> RawVec<T, A> {

/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize)
-> Result<(), CollectionAllocErr> {
-> Result<(), CollectionAllocErr<A::Err>> {

self.reserve_internal(used_cap, needed_extra_cap, Fallible, Exact)
}
Expand Down Expand Up @@ -410,7 +413,7 @@ impl<T, A: Alloc> RawVec<T, A> {
pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Exact) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocErr) => unreachable!(),
Err(AllocErr(_)) => unreachable!(),
Ok(()) => { /* yay */ }
}
}
Expand All @@ -419,7 +422,7 @@ impl<T, A: Alloc> RawVec<T, A> {
/// needed_extra_cap` elements. This logic is used in amortized reserve methods.
/// Returns `(new_capacity, new_alloc_size)`.
fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize)
-> Result<usize, CollectionAllocErr> {
-> Result<usize, CollectionAllocErr<A::Err>> {

// Nothing we can really do about these checks :(
let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
Expand All @@ -431,7 +434,7 @@ impl<T, A: Alloc> RawVec<T, A> {

/// The same as `reserve`, but returns on errors instead of panicking or aborting.
pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize)
-> Result<(), CollectionAllocErr> {
-> Result<(), CollectionAllocErr<A::Err>> {
self.reserve_internal(used_cap, needed_extra_cap, Fallible, Amortized)
}

Expand Down Expand Up @@ -490,7 +493,7 @@ impl<T, A: Alloc> RawVec<T, A> {
pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Amortized) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocErr) => unreachable!(),
Err(AllocErr(_)) => unreachable!(),
Ok(()) => { /* yay */ }
}
}
Expand Down Expand Up @@ -538,7 +541,7 @@ impl<T, A: Alloc> RawVec<T, A> {

let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
// FIXME: may crash and burn on over-reserve
alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
alloc_guard::<A::Err>(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
match self.a.grow_in_place(
NonNull::from(self.ptr).cast(), old_layout, new_layout.size(),
) {
Expand Down Expand Up @@ -636,10 +639,8 @@ impl<T, A: Alloc> RawVec<T, A> {
needed_extra_cap: usize,
fallibility: Fallibility,
strategy: ReserveStrategy,
) -> Result<(), CollectionAllocErr> {
) -> Result<(), CollectionAllocErr<A::Err>> {
unsafe {
use crate::alloc::AllocErr;

// NOTE: we don't early branch on ZSTs here because we want this
// to actually catch "asking for more than usize::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
Expand Down Expand Up @@ -669,11 +670,11 @@ impl<T, A: Alloc> RawVec<T, A> {
};

match (&res, fallibility) {
(Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
(Err(_), Infallible) => handle_alloc_error(new_layout),
_ => {}
}

self.ptr = res?.cast().into();
self.ptr = res.map_err(|e| CollectionAllocErr::AllocErr(e))?.cast().into();
self.cap = new_cap;

Ok(())
Expand Down Expand Up @@ -731,7 +732,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
// all 4GB in user-space. e.g., PAE or x32

#[inline]
fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
fn alloc_guard<E>(alloc_size: usize) -> Result<(), CollectionAllocErr<E>> {
if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize {
Err(CapacityOverflow)
} else {
Expand Down
Loading