Skip to content

Commit a98fe63

Browse files
committed
Add associated error type to allocators
We will use this for fallibility polymorphism
1 parent 4e69e86 commit a98fe63

File tree

5 files changed

+116
-84
lines changed

5 files changed

+116
-84
lines changed

src/liballoc/alloc.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
170170
__rust_alloc_zeroed(layout.size(), layout.align())
171171
}
172172

173+
#[cfg(not(test))]
174+
#[unstable(feature = "allocator_api", issue = "32838")]
175+
impl AllocHelper for Global {
176+
type Err = AllocErr;
177+
}
178+
173179
#[cfg(not(test))]
174180
#[unstable(feature = "allocator_api", issue = "32838")]
175181
unsafe impl Alloc for Global {

src/liballoc/boxed.rs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ use core::ptr::{self, NonNull, Unique};
8888
use core::task::{Context, Poll};
8989

9090
use crate::alloc::{
91-
Stage0Alloc as Alloc, Global, Layout, handle_alloc_error, stage0_phantom, stage0_unphantom
91+
Stage0Alloc as Alloc, AllocHelper, AllocErr, Global, Layout, handle_alloc_error, stage0_phantom, stage0_unphantom
9292
};
9393
use crate::vec::Vec;
9494
use crate::raw_vec::RawVec;
@@ -137,7 +137,7 @@ impl<T> Box<T> {
137137
}
138138
}
139139

140-
impl<T, A: Alloc> Box<T, A> {
140+
impl<T, A: Alloc<Err = AllocErr>> Box<T, A> {
141141
/// Allocates memory in the given allocator and then places `x` into it.
142142
///
143143
/// This doesn't actually allocate if `T` is zero-sized.
@@ -210,7 +210,7 @@ impl<T: ?Sized> Box<T> {
210210
}
211211
}
212212

213-
impl<T: ?Sized, A: Alloc> Box<T, A> {
213+
impl<T: ?Sized, A> Box<T, A> {
214214
/// Constructs a box from a raw pointer in the given allocator.
215215
///
216216
/// This is similar to the [`Box::from_raw`] function, but assumes
@@ -394,29 +394,29 @@ unsafe impl<#[may_dangle] T: ?Sized, A> Drop for Box<T, A> {
394394
}
395395

396396
#[stable(feature = "rust1", since = "1.0.0")]
397-
impl<T: Default, A: Alloc + Default> Default for Box<T, A> {
397+
impl<T: Default, A: Alloc<Err = AllocErr> + Default> Default for Box<T, A> {
398398
/// Creates a `Box<T, A>`, with the `Default` value for T.
399399
fn default() -> Box<T, A> {
400400
Box::new_in(Default::default(), A::default())
401401
}
402402
}
403403

404404
#[stable(feature = "rust1", since = "1.0.0")]
405-
impl<T, A: Alloc + Default> Default for Box<[T], A> {
405+
impl<T, A: Alloc<Err = AllocErr> + Default> Default for Box<[T], A> {
406406
fn default() -> Box<[T], A> {
407407
Box::<[T; 0], A>::new_in([], A::default())
408408
}
409409
}
410410

411411
#[stable(feature = "default_box_extra", since = "1.17.0")]
412-
impl<A: Alloc + Default> Default for Box<str, A> {
412+
impl<A: Alloc<Err = AllocErr> + Default> Default for Box<str, A> {
413413
fn default() -> Box<str, A> {
414414
unsafe { from_boxed_utf8_unchecked(Default::default()) }
415415
}
416416
}
417417

418418
#[stable(feature = "rust1", since = "1.0.0")]
419-
impl<T: Clone, A: Alloc + Clone> Clone for Box<T, A> {
419+
impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<T, A> {
420420
/// Returns a new box with a `clone()` of this box's contents.
421421
///
422422
/// # Examples
@@ -448,9 +448,8 @@ impl<T: Clone, A: Alloc + Clone> Clone for Box<T, A> {
448448
}
449449
}
450450

451-
452451
#[stable(feature = "box_slice_clone", since = "1.3.0")]
453-
impl<A: Alloc + Clone> Clone for Box<str, A> {
452+
impl<A: Alloc<Err = AllocErr> + Clone> Clone for Box<str, A> {
454453
fn clone(&self) -> Self {
455454
let len = self.len();
456455
let buf = RawVec::with_capacity_in(len, stage0_unphantom(self.1.clone()));
@@ -559,7 +558,7 @@ impl<T: ?Sized + Hasher, A> Hasher for Box<T, A> {
559558
}
560559

561560
#[stable(feature = "from_for_ptrs", since = "1.6.0")]
562-
impl<T, A: Alloc + Default> From<T> for Box<T, A> {
561+
impl<T, A: Alloc<Err = AllocErr> + Default> From<T> for Box<T, A> {
563562
/// Converts a generic type `T` into a `Box<T>`
564563
///
565564
/// The conversion allocates on the heap and moves `t`
@@ -588,7 +587,7 @@ impl<T: ?Sized, A> From<Box<T, A>> for Pin<Box<T, A>> {
588587
}
589588

590589
#[stable(feature = "box_from_slice", since = "1.17.0")]
591-
impl<T: Copy, A: Alloc + Default> From<&[T]> for Box<[T], A> {
590+
impl<T: Copy, A: Alloc<Err = AllocErr> + Default> From<&[T]> for Box<[T], A> {
592591
/// Converts a `&[T]` into a `Box<[T]>`
593592
///
594593
/// This conversion allocates on the heap
@@ -611,7 +610,7 @@ impl<T: Copy, A: Alloc + Default> From<&[T]> for Box<[T], A> {
611610
}
612611

613612
#[stable(feature = "box_from_slice", since = "1.17.0")]
614-
impl<A: Alloc + Default> From<&str> for Box<str, A> {
613+
impl<A: Alloc<Err = AllocErr> + Default> From<&str> for Box<str, A> {
615614
/// Converts a `&str` into a `Box<str>`
616615
///
617616
/// This conversion allocates on the heap
@@ -629,7 +628,7 @@ impl<A: Alloc + Default> From<&str> for Box<str, A> {
629628
}
630629

631630
#[stable(feature = "boxed_str_conv", since = "1.19.0")]
632-
impl<A: Alloc> From<Box<str, A>> for Box<[u8], A> {
631+
impl<A> From<Box<str, A>> for Box<[u8], A> {
633632
/// Converts a `Box<str>>` into a `Box<[u8]>`
634633
///
635634
/// This conversion does not allocate on the heap and happens in place.
@@ -652,7 +651,7 @@ impl<A: Alloc> From<Box<str, A>> for Box<[u8], A> {
652651
}
653652
}
654653

655-
impl<A: Alloc> Box<dyn Any, A> {
654+
impl<A> Box<dyn Any, A> {
656655
#[inline]
657656
#[stable(feature = "rust1", since = "1.0.0")]
658657
/// Attempt to downcast the box to a concrete type.
@@ -683,7 +682,7 @@ impl<A: Alloc> Box<dyn Any, A> {
683682
}
684683
}
685684

686-
impl<A: Alloc> Box<dyn Any + Send, A> {
685+
impl<A: Alloc<Err=AllocErr>> Box<dyn Any + Send, A> {
687686
#[inline]
688687
#[stable(feature = "rust1", since = "1.0.0")]
689688
/// Attempt to downcast the box to a concrete type.
@@ -885,7 +884,7 @@ impl<A> FromIterator<A> for Box<[A]> {
885884
}
886885

887886
#[stable(feature = "box_slice_clone", since = "1.3.0")]
888-
impl<T: Clone, A: Alloc + Clone> Clone for Box<[T], A> {
887+
impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<[T], A> {
889888
fn clone(&self) -> Self {
890889
let mut new = BoxBuilder {
891890
data: RawVec::with_capacity_in(self.len(), stage0_unphantom(self.1.clone())),
@@ -906,20 +905,20 @@ impl<T: Clone, A: Alloc + Clone> Clone for Box<[T], A> {
906905
return unsafe { new.into_box() };
907906

908907
// Helper type for responding to panics correctly.
909-
struct BoxBuilder<T, A: Alloc> {
908+
struct BoxBuilder<T, A: Alloc<Err = AllocErr> + AllocHelper<Err = AllocErr>> {
910909
data: RawVec<T, A>,
911910
len: usize,
912911
}
913912

914-
impl<T, A: Alloc> BoxBuilder<T, A> {
913+
impl<T, A: Alloc<Err = AllocErr>> BoxBuilder<T, A> {
915914
unsafe fn into_box(self) -> Box<[T], A> {
916915
let raw = ptr::read(&self.data);
917916
mem::forget(self);
918917
raw.into_box()
919918
}
920919
}
921920

922-
impl<T, A: Alloc> Drop for BoxBuilder<T, A> {
921+
impl<T, A: Alloc<Err = AllocErr>> Drop for BoxBuilder<T, A> {
923922
fn drop(&mut self) {
924923
let mut data = self.data.ptr();
925924
let max = unsafe { data.add(self.len) };

src/liballoc/raw_vec.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use core::ops::Drop;
77
use core::ptr::{self, NonNull, Unique};
88
use core::slice;
99

10-
use crate::alloc::{Stage0Alloc as Alloc, Layout, Global, handle_alloc_error};
11-
use crate::collections::CollectionAllocErr::{self, *};
10+
use crate::alloc::{Stage0Alloc as Alloc, AllocHelper, AllocErr, Layout, Global, handle_alloc_error};
11+
use crate::collections::CollectionAllocErr;
1212
use crate::boxed::Box;
1313

1414
/// A low-level utility for more ergonomically allocating, reallocating, and deallocating
@@ -39,13 +39,13 @@ use crate::boxed::Box;
3939
/// field. This allows zero-sized types to not be special-cased by consumers of
4040
/// this type.
4141
#[allow(missing_debug_implementations)]
42-
pub struct RawVec<T, A: Alloc = Global> {
42+
pub struct RawVec<T, A: Alloc + AllocHelper<Err = AllocErr> = Global> {
4343
ptr: Unique<T>,
4444
cap: usize,
4545
a: A,
4646
}
4747

48-
impl<T, A: Alloc> RawVec<T, A> {
48+
impl<T, A: Alloc + AllocHelper<Err = AllocErr>> RawVec<T, A> {
4949
/// Like `new` but parameterized over the choice of allocator for
5050
/// the returned RawVec.
5151
pub const fn new_in(a: A) -> Self {
@@ -146,7 +146,7 @@ impl<T> RawVec<T, Global> {
146146
}
147147
}
148148

149-
impl<T, A: Alloc> RawVec<T, A> {
149+
impl<T, A: Alloc + AllocHelper<Err = AllocErr>> RawVec<T, A> {
150150
/// Reconstitutes a RawVec from a pointer, capacity, and allocator.
151151
///
152152
/// # Undefined Behavior
@@ -189,7 +189,7 @@ impl<T> RawVec<T, Global> {
189189
}
190190
}
191191

192-
impl<T, A: Alloc> RawVec<T, A> {
192+
impl<T, A: Alloc + AllocHelper<Err = AllocErr>> RawVec<T, A> {
193193
/// Gets a raw pointer to the start of the allocation. Note that this is
194194
/// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must
195195
/// be careful.
@@ -409,8 +409,8 @@ impl<T, A: Alloc> RawVec<T, A> {
409409
/// Aborts on OOM
410410
pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
411411
match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Exact) {
412-
Err(CapacityOverflow) => capacity_overflow(),
413-
Err(AllocErr) => unreachable!(),
412+
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
413+
Err(CollectionAllocErr::AllocErr) => unreachable!(),
414414
Ok(()) => { /* yay */ }
415415
}
416416
}
@@ -422,7 +422,7 @@ impl<T, A: Alloc> RawVec<T, A> {
422422
-> Result<usize, CollectionAllocErr> {
423423

424424
// Nothing we can really do about these checks :(
425-
let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
425+
let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CollectionAllocErr::CapacityOverflow)?;
426426
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
427427
let double_cap = self.cap * 2;
428428
// `double_cap` guarantees exponential growth.
@@ -489,8 +489,8 @@ impl<T, A: Alloc> RawVec<T, A> {
489489
/// ```
490490
pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
491491
match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Amortized) {
492-
Err(CapacityOverflow) => capacity_overflow(),
493-
Err(AllocErr) => unreachable!(),
492+
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
493+
Err(CollectionAllocErr::AllocErr) => unreachable!(),
494494
Ok(()) => { /* yay */ }
495495
}
496496
}
@@ -629,7 +629,7 @@ enum ReserveStrategy {
629629

630630
use ReserveStrategy::*;
631631

632-
impl<T, A: Alloc> RawVec<T, A> {
632+
impl<T, A: Alloc + AllocHelper<Err = AllocErr>> RawVec<T, A> {
633633
fn reserve_internal(
634634
&mut self,
635635
used_cap: usize,
@@ -638,8 +638,6 @@ impl<T, A: Alloc> RawVec<T, A> {
638638
strategy: ReserveStrategy,
639639
) -> Result<(), CollectionAllocErr> {
640640
unsafe {
641-
use crate::alloc::AllocErr;
642-
643641
// NOTE: we don't early branch on ZSTs here because we want this
644642
// to actually catch "asking for more than usize::MAX" in that case.
645643
// If we make it past the first branch then we are guaranteed to
@@ -653,10 +651,10 @@ impl<T, A: Alloc> RawVec<T, A> {
653651

654652
// Nothing we can really do about these checks :(
655653
let new_cap = match strategy {
656-
Exact => used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?,
654+
Exact => used_cap.checked_add(needed_extra_cap).ok_or(CollectionAllocErr::CapacityOverflow)?,
657655
Amortized => self.amortized_new_size(used_cap, needed_extra_cap)?,
658656
};
659-
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
657+
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CollectionAllocErr::CapacityOverflow)?;
660658

661659
alloc_guard(new_layout.size())?;
662660

@@ -682,7 +680,7 @@ impl<T, A: Alloc> RawVec<T, A> {
682680

683681
}
684682

685-
impl<T, A: Alloc> RawVec<T, A> {
683+
impl<T, A: Alloc + AllocHelper<Err = AllocErr>> RawVec<T, A> {
686684
/// Converts the entire buffer into `Box<[T], A>`.
687685
///
688686
/// While it is not *strictly* Undefined Behavior to call
@@ -701,7 +699,7 @@ impl<T, A: Alloc> RawVec<T, A> {
701699
}
702700
}
703701

704-
impl<T, A: Alloc> RawVec<T, A> {
702+
impl<T, A: Alloc + AllocHelper<Err = AllocErr>> RawVec<T, A> {
705703
/// Frees the memory owned by the RawVec *without* trying to Drop its contents.
706704
pub unsafe fn dealloc_buffer(&mut self) {
707705
let elem_size = mem::size_of::<T>();
@@ -713,7 +711,7 @@ impl<T, A: Alloc> RawVec<T, A> {
713711
}
714712
}
715713

716-
unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
714+
unsafe impl<#[may_dangle] T, A: Alloc + AllocHelper<Err = AllocErr>> Drop for RawVec<T, A> {
717715
/// Frees the memory owned by the RawVec *without* trying to Drop its contents.
718716
fn drop(&mut self) {
719717
unsafe { self.dealloc_buffer(); }
@@ -734,7 +732,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
734732
#[inline]
735733
fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
736734
if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize {
737-
Err(CapacityOverflow)
735+
Err(CollectionAllocErr::CapacityOverflow)
738736
} else {
739737
Ok(())
740738
}

src/liballoc/str.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use core::ptr;
3535
use core::iter::FusedIterator;
3636
use core::unicode::conversions;
3737

38-
use crate::alloc::{Stage0Alloc as Alloc, stage0_unphantom};
38+
use crate::alloc::{Stage0Alloc as Alloc, AllocHelper, AllocErr, stage0_unphantom};
3939
use crate::borrow::ToOwned;
4040
use crate::boxed::Box;
4141
use crate::slice::{SliceConcatExt, SliceIndex};
@@ -579,6 +579,6 @@ impl str {
579579
/// ```
580580
#[stable(feature = "str_box_extras", since = "1.20.0")]
581581
#[inline]
582-
pub unsafe fn from_boxed_utf8_unchecked<A: Alloc>(v: Box<[u8], A>) -> Box<str, A> {
582+
pub unsafe fn from_boxed_utf8_unchecked<A: Alloc + AllocHelper<Err=AllocErr>>(v: Box<[u8], A>) -> Box<str, A> {
583583
Box::map_raw(v, |p| p as *mut str)
584584
}

0 commit comments

Comments
 (0)