Skip to content

Commit b6aad76

Browse files
committed
box, RawVec: Generalize to not neccessary abort on OOM
1 parent 4fabdec commit b6aad76

File tree

9 files changed

+202
-181
lines changed

9 files changed

+202
-181
lines changed

src/liballoc/abort_adapter.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ unsafe impl<A: Alloc> Alloc for AbortAdapter<A> {
4848
ptr: NonNull<u8>,
4949
layout: Layout,
5050
new_size: usize) -> Result<NonNull<u8>, Self::Err> {
51-
self.0.realloc(ptr, layout, new_size).or_else(|_| handle_alloc_error(layout))
51+
self.0.realloc(ptr, layout, new_size).or_else(|_| {
52+
let layout = Layout::from_size_align_unchecked(new_size, layout.align());
53+
handle_alloc_error(layout)
54+
})
5255
}
5356

5457
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, Self::Err> {

src/liballoc/boxed.rs

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ use core::ops::{
8787
use core::ptr::{self, NonNull, Unique};
8888
use core::task::{Context, Poll};
8989

90+
use crate::abort_adapter::AbortAdapter;
9091
use crate::alloc::{
91-
Stage0Alloc as Alloc, AllocHelper, AllocErr, Global, Layout, handle_alloc_error, stage0_phantom, stage0_unphantom
92+
Stage0Alloc as Alloc, Global, Layout, stage0_phantom, stage0_unphantom
9293
};
9394
use crate::vec::Vec;
9495
use crate::raw_vec::RawVec;
@@ -101,7 +102,7 @@ use crate::str::from_boxed_utf8_unchecked;
101102
#[lang = "owned_box"]
102103
#[fundamental]
103104
#[stable(feature = "rust1", since = "1.0.0")]
104-
pub struct Box<T: ?Sized, A = Global>(Unique<T>, pub(crate) A);
105+
pub struct Box<T: ?Sized, A = AbortAdapter<Global>>(Unique<T>, pub(crate) A);
105106

106107
// Use a variant with PhantomData in stage0, to satisfy the limitations of
107108
// DispatchFromDyn in 1.35.
@@ -110,7 +111,7 @@ pub struct Box<T: ?Sized, A = Global>(Unique<T>, pub(crate) A);
110111
#[lang = "owned_box"]
111112
#[fundamental]
112113
#[stable(feature = "rust1", since = "1.0.0")]
113-
pub struct Box<T: ?Sized, A = Global>(Unique<T>, pub(crate) PhantomData<A>);
114+
pub struct Box<T: ?Sized, A = AbortAdapter<Global>>(Unique<T>, pub(crate) PhantomData<A>);
114115

115116
impl<T> Box<T> {
116117
/// Allocates memory on the heap and then places `x` into it.
@@ -137,7 +138,7 @@ impl<T> Box<T> {
137138
}
138139
}
139140

140-
impl<T, A: Alloc<Err = AllocErr>> Box<T, A> {
141+
impl<T, A: Alloc> Box<T, A> {
141142
/// Allocates memory in the given allocator and then places `x` into it.
142143
///
143144
/// This doesn't actually allocate if `T` is zero-sized.
@@ -151,15 +152,15 @@ impl<T, A: Alloc<Err = AllocErr>> Box<T, A> {
151152
/// ```
152153
#[unstable(feature = "allocator_api", issue = "32838")]
153154
#[inline(always)]
154-
pub fn new_in(x: T, a: A) -> Box<T, A> {
155+
pub fn new_in(x: T, a: A) -> Result<Box<T, A>, A::Err> {
155156
let mut a = a;
156157
let layout = Layout::for_value(&x);
157158
let size = layout.size();
158159
let ptr = if size == 0 {
159160
Unique::empty()
160161
} else {
161162
unsafe {
162-
let ptr = a.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
163+
let ptr = a.alloc(layout)?;
163164
ptr.cast().into()
164165
}
165166
};
@@ -168,15 +169,15 @@ impl<T, A: Alloc<Err = AllocErr>> Box<T, A> {
168169
unsafe {
169170
ptr::write(ptr.as_ptr() as *mut T, x);
170171
}
171-
Box(ptr, stage0_phantom(a))
172+
Ok(Box(ptr, stage0_phantom(a)))
172173
}
173174

174175
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
175176
/// `x` will be pinned in memory and unable to be moved.
176177
#[unstable(feature = "allocator_api", issue = "32838")]
177178
#[inline(always)]
178-
pub fn pin_in(x: T, a: A) -> Pin<Box<T, A>> {
179-
Box::new_in(x, a).into()
179+
pub fn pin_in(x: T, a: A) -> Result<Pin<Box<T, A>>, A::Err> {
180+
Box::new_in(x, a).map(Into::into)
180181
}
181182
}
182183

@@ -206,7 +207,7 @@ impl<T: ?Sized> Box<T> {
206207
#[stable(feature = "box_raw", since = "1.4.0")]
207208
#[inline]
208209
pub unsafe fn from_raw(raw: *mut T) -> Self {
209-
Box(Unique::new_unchecked(raw), stage0_phantom(Global))
210+
Box(Unique::new_unchecked(raw), stage0_phantom(AbortAdapter(Global)))
210211
}
211212
}
212213

@@ -272,7 +273,7 @@ impl<T: ?Sized, A> Box<T, A> {
272273
/// ```
273274
#[stable(feature = "box_raw", since = "1.4.0")]
274275
#[inline]
275-
pub fn into_raw(b: Box<T, A>) -> *mut T {
276+
pub fn into_raw(b: Self) -> *mut T {
276277
Box::into_raw_non_null(b).as_ptr()
277278
}
278279

@@ -322,6 +323,21 @@ impl<T: ?Sized, A> Box<T, A> {
322323
unsafe { Unique::new_unchecked(unique) }
323324
}
324325

326+
327+
#[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
328+
issue = "27730")]
329+
#[inline]
330+
pub fn into_both(mut b: Self) -> (Unique<T>, A) {
331+
let unique = b.0;
332+
let alloc = unsafe {
333+
let mut a = mem::uninitialized();
334+
mem::swap(&mut a, &mut b.1);
335+
a
336+
};
337+
mem::forget(b);
338+
(unique, alloc)
339+
}
340+
325341
/// Consumes and leaks the `Box`, returning a mutable reference,
326342
/// `&'a mut T`. Note that the type `T` must outlive the chosen lifetime
327343
/// `'a`. If the type has only static references, or none at all, then this
@@ -365,7 +381,7 @@ impl<T: ?Sized, A> Box<T, A> {
365381
/// ```
366382
#[stable(feature = "box_leak", since = "1.26.0")]
367383
#[inline]
368-
pub fn leak<'a>(b: Box<T, A>) -> &'a mut T
384+
pub fn leak<'a>(b: Self) -> &'a mut T
369385
where
370386
T: 'a // Technically not needed, but kept to be explicit.
371387
{
@@ -386,6 +402,7 @@ impl<T: ?Sized, A> Box<T, A> {
386402
}
387403
}
388404

405+
389406
#[stable(feature = "rust1", since = "1.0.0")]
390407
unsafe impl<#[may_dangle] T: ?Sized, A> Drop for Box<T, A> {
391408
fn drop(&mut self) {
@@ -394,29 +411,31 @@ unsafe impl<#[may_dangle] T: ?Sized, A> Drop for Box<T, A> {
394411
}
395412

396413
#[stable(feature = "rust1", since = "1.0.0")]
397-
impl<T: Default, A: Alloc<Err = AllocErr> + Default> Default for Box<T, A> {
414+
impl<T: Default, A: Alloc<Err = !> + Default> Default for Box<T, A> {
398415
/// Creates a `Box<T, A>`, with the `Default` value for T.
399416
fn default() -> Box<T, A> {
400-
Box::new_in(Default::default(), A::default())
417+
let Ok(b) = Box::new_in(Default::default(), A::default());
418+
b
401419
}
402420
}
403421

404422
#[stable(feature = "rust1", since = "1.0.0")]
405-
impl<T, A: Alloc<Err = AllocErr> + Default> Default for Box<[T], A> {
423+
impl<T, A: Alloc<Err=!> + Default> Default for Box<[T], A> {
406424
fn default() -> Box<[T], A> {
407-
Box::<[T; 0], A>::new_in([], A::default())
425+
let Ok(b) = Box::<[T; 0], A>::new_in([], Default::default());
426+
b
408427
}
409428
}
410429

411430
#[stable(feature = "default_box_extra", since = "1.17.0")]
412-
impl<A: Alloc<Err = AllocErr> + Default> Default for Box<str, A> {
431+
impl<A: Alloc<Err = !> + Default> Default for Box<str, A> {
413432
fn default() -> Box<str, A> {
414433
unsafe { from_boxed_utf8_unchecked(Default::default()) }
415434
}
416435
}
417436

418437
#[stable(feature = "rust1", since = "1.0.0")]
419-
impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<T, A> {
438+
impl<T: Clone, A: Alloc<Err = !> + Clone> Clone for Box<T, A> {
420439
/// Returns a new box with a `clone()` of this box's contents.
421440
///
422441
/// # Examples
@@ -427,8 +446,9 @@ impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<T, A> {
427446
/// ```
428447
#[rustfmt::skip]
429448
#[inline]
430-
fn clone(&self) -> Box<T, A> {
431-
Box::new_in((**self).clone(), stage0_unphantom(self.1.clone()))
449+
fn clone(&self) -> Self {
450+
let Ok(b) = Box::new_in((**self).clone(), stage0_unphantom(self.1.clone()));
451+
b
432452
}
433453
/// Copies `source`'s contents into `self` without creating a new allocation.
434454
///
@@ -443,23 +463,24 @@ impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<T, A> {
443463
/// assert_eq!(*y, 5);
444464
/// ```
445465
#[inline]
446-
fn clone_from(&mut self, source: &Box<T, A>) {
466+
fn clone_from(&mut self, source: &Self) {
447467
(**self).clone_from(&(**source));
448468
}
449469
}
450470

451471
#[stable(feature = "box_slice_clone", since = "1.3.0")]
452-
impl<A: Alloc<Err = AllocErr> + Clone> Clone for Box<str, A> {
472+
impl<A: Alloc<Err = !> + Clone> Clone for Box<str, A> {
453473
fn clone(&self) -> Self {
454474
let len = self.len();
455-
let buf = RawVec::with_capacity_in(len, stage0_unphantom(self.1.clone()));
475+
let Ok(buf) = RawVec::with_capacity_in(len, stage0_unphantom(self.1.clone()));
456476
unsafe {
457477
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
458478
from_boxed_utf8_unchecked(buf.into_box())
459479
}
460480
}
461481
}
462482

483+
/// Just the contents are compared, the allocator is ignored
463484
#[stable(feature = "rust1", since = "1.0.0")]
464485
impl<T: ?Sized + PartialEq, A> PartialEq for Box<T, A> {
465486
#[inline]
@@ -471,6 +492,7 @@ impl<T: ?Sized + PartialEq, A> PartialEq for Box<T, A> {
471492
PartialEq::ne(&**self, &**other)
472493
}
473494
}
495+
/// Just the contents are compared, the allocator is ignored
474496
#[stable(feature = "rust1", since = "1.0.0")]
475497
impl<T: ?Sized + PartialOrd, A> PartialOrd for Box<T, A> {
476498
#[inline]
@@ -494,23 +516,27 @@ impl<T: ?Sized + PartialOrd, A> PartialOrd for Box<T, A> {
494516
PartialOrd::gt(&**self, &**other)
495517
}
496518
}
519+
/// Just the contents are compared, the allocator is ignored
497520
#[stable(feature = "rust1", since = "1.0.0")]
498521
impl<T: ?Sized + Ord, A> Ord for Box<T, A> {
499522
#[inline]
500523
fn cmp(&self, other: &Box<T, A>) -> Ordering {
501524
Ord::cmp(&**self, &**other)
502525
}
503526
}
527+
/// Just the contents are compared, the allocator is ignored
504528
#[stable(feature = "rust1", since = "1.0.0")]
505529
impl<T: ?Sized + Eq, A> Eq for Box<T, A> {}
506530

531+
/// Just the contents are compared, the allocator is ignored
507532
#[stable(feature = "rust1", since = "1.0.0")]
508533
impl<T: ?Sized + Hash, A> Hash for Box<T, A> {
509534
fn hash<H: Hasher>(&self, state: &mut H) {
510535
(**self).hash(state);
511536
}
512537
}
513538

539+
/// Just the contents are compared, the allocator is ignored
514540
#[stable(feature = "indirect_hasher_impl", since = "1.22.0")]
515541
impl<T: ?Sized + Hasher, A> Hasher for Box<T, A> {
516542
fn finish(&self) -> u64 {
@@ -558,7 +584,7 @@ impl<T: ?Sized + Hasher, A> Hasher for Box<T, A> {
558584
}
559585

560586
#[stable(feature = "from_for_ptrs", since = "1.6.0")]
561-
impl<T, A: Alloc<Err = AllocErr> + Default> From<T> for Box<T, A> {
587+
impl<T, A: Alloc<Err = !> + Default> From<T> for Box<T, A> {
562588
/// Converts a generic type `T` into a `Box<T>`
563589
///
564590
/// The conversion allocates on the heap and moves `t`
@@ -572,7 +598,8 @@ impl<T, A: Alloc<Err = AllocErr> + Default> From<T> for Box<T, A> {
572598
/// assert_eq!(Box::from(x), boxed);
573599
/// ```
574600
fn from(t: T) -> Self {
575-
Box::new_in(t, A::default())
601+
let Ok(b) = Box::new_in(t, Default::default());
602+
b
576603
}
577604
}
578605

@@ -587,7 +614,7 @@ impl<T: ?Sized, A> From<Box<T, A>> for Pin<Box<T, A>> {
587614
}
588615

589616
#[stable(feature = "box_from_slice", since = "1.17.0")]
590-
impl<T: Copy, A: Alloc<Err = AllocErr> + Default> From<&[T]> for Box<[T], A> {
617+
impl<T: Copy, A: Alloc<Err = !> + Default> From<&[T]> for Box<[T], A> {
591618
/// Converts a `&[T]` into a `Box<[T]>`
592619
///
593620
/// This conversion allocates on the heap
@@ -603,14 +630,15 @@ impl<T: Copy, A: Alloc<Err = AllocErr> + Default> From<&[T]> for Box<[T], A> {
603630
/// ```
604631
fn from(slice: &[T]) -> Box<[T], A> {
605632
let a = A::default();
606-
let mut boxed = unsafe { RawVec::with_capacity_in(slice.len(), a).into_box() };
633+
let Ok(vec) = RawVec::with_capacity_in(slice.len(), a);
634+
let mut boxed = unsafe { vec.into_box() };
607635
boxed.copy_from_slice(slice);
608636
boxed
609637
}
610638
}
611639

612640
#[stable(feature = "box_from_slice", since = "1.17.0")]
613-
impl<A: Alloc<Err = AllocErr> + Default> From<&str> for Box<str, A> {
641+
impl<A: Alloc<Err = !> + Default> From<&str> for Box<str, A> {
614642
/// Converts a `&str` into a `Box<str>`
615643
///
616644
/// This conversion allocates on the heap
@@ -682,7 +710,7 @@ impl<A> Box<dyn Any, A> {
682710
}
683711
}
684712

685-
impl<A: Alloc<Err=AllocErr>> Box<dyn Any + Send, A> {
713+
impl<A: Alloc<Err=!>> Box<dyn Any + Send, A> {
686714
#[inline]
687715
#[stable(feature = "rust1", since = "1.0.0")]
688716
/// Attempt to downcast the box to a concrete type.
@@ -853,9 +881,9 @@ impl<A, F: Fn<A> + ?Sized, Alloc> Fn<A> for Box<F, Alloc> {
853881
#[rustc_paren_sugar]
854882
#[unstable(feature = "fnbox",
855883
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
856-
pub trait FnBox<Args>: FnOnce<Args> {
884+
pub trait FnBox<Args, A: Alloc = AbortAdapter<Global>>: FnOnce<Args> {
857885
/// Performs the call operation.
858-
fn call_box(self: Box<Self>, args: Args) -> Self::Output;
886+
fn call_box(self: Box<Self, A>, args: Args) -> Self::Output;
859887
}
860888

861889
//FIXME: Make generic over A along with DispatchFromDyn.
@@ -884,10 +912,12 @@ impl<A> FromIterator<A> for Box<[A]> {
884912
}
885913

886914
#[stable(feature = "box_slice_clone", since = "1.3.0")]
887-
impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<[T], A> {
915+
impl<T: Clone, A: Alloc<Err = !> + Clone> Clone for Box<[T], A> {
888916
fn clone(&self) -> Self {
917+
let Ok(b) = RawVec::with_capacity_in(self.len(), self.1.clone());
918+
889919
let mut new = BoxBuilder {
890-
data: RawVec::with_capacity_in(self.len(), stage0_unphantom(self.1.clone())),
920+
data: b,
891921
len: 0,
892922
};
893923

@@ -905,20 +935,20 @@ impl<T: Clone, A: Alloc<Err = AllocErr> + Clone> Clone for Box<[T], A> {
905935
return unsafe { new.into_box() };
906936

907937
// Helper type for responding to panics correctly.
908-
struct BoxBuilder<T, A: Alloc<Err = AllocErr> + AllocHelper<Err = AllocErr>> {
938+
struct BoxBuilder<T, A: Alloc> {
909939
data: RawVec<T, A>,
910940
len: usize,
911941
}
912942

913-
impl<T, A: Alloc<Err = AllocErr>> BoxBuilder<T, A> {
943+
impl<T, A: Alloc> BoxBuilder<T, A> {
914944
unsafe fn into_box(self) -> Box<[T], A> {
915945
let raw = ptr::read(&self.data);
916946
mem::forget(self);
917947
raw.into_box()
918948
}
919949
}
920950

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

src/liballoc/collections/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,24 @@ use crate::alloc::{AllocErr, LayoutErr};
4646
/// Augments `AllocErr` with a CapacityOverflow variant.
4747
#[derive(Clone, PartialEq, Eq, Debug)]
4848
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
49-
pub enum CollectionAllocErr {
49+
pub enum CollectionAllocErr<E> {
5050
/// Error due to the computed capacity exceeding the collection's maximum
5151
/// (usually `isize::MAX` bytes).
5252
CapacityOverflow,
5353
/// Error due to the allocator (see the `AllocErr` type's docs).
54-
AllocErr,
54+
AllocErr(E),
5555
}
5656

5757
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
58-
impl From<AllocErr> for CollectionAllocErr {
58+
impl From<AllocErr> for CollectionAllocErr<AllocErr> {
5959
#[inline]
6060
fn from(AllocErr: AllocErr) -> Self {
61-
CollectionAllocErr::AllocErr
61+
CollectionAllocErr::AllocErr(AllocErr)
6262
}
6363
}
6464

6565
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
66-
impl From<LayoutErr> for CollectionAllocErr {
66+
impl<E> From<LayoutErr> for CollectionAllocErr<E> {
6767
#[inline]
6868
fn from(_: LayoutErr) -> Self {
6969
CollectionAllocErr::CapacityOverflow

0 commit comments

Comments
 (0)