Skip to content
This repository has been archived by the owner on Nov 27, 2020. It is now read-only.

Commit

Permalink
Require Error = ! for "infallible allocation
Browse files Browse the repository at this point in the history
  • Loading branch information
Ericson2314 committed Nov 30, 2019
1 parent 8aec886 commit 005f1b5
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 177 deletions.
65 changes: 47 additions & 18 deletions src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ use crate::{
clone::CloneIn,
collections::CollectionAllocErr,
raw_vec::RawVec,
UncheckedResultExt,
};
use core::{
any::Any,
Expand Down Expand Up @@ -184,8 +183,12 @@ impl<T, A: AllocRef> Box<T, A> {
/// ```
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn new_in(x: T, a: A) -> Self {
unsafe { Self::try_new_in(x, a).unwrap_unchecked() }
pub fn new_in(x: T, a: A) -> Self
where
A: AllocRef<Error = !>,
{
let Ok(b) = Self::try_new_in(x, a);
b
}

/// Tries to allocate memory with the given allocator and then places `x` into it.
Expand Down Expand Up @@ -234,8 +237,12 @@ impl<T, A: AllocRef> Box<T, A> {
/// ```
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn new_uninit_in(a: A) -> Box<mem::MaybeUninit<T>, A> {
unsafe { Self::try_new_uninit_in(a).unwrap_unchecked() }
pub fn new_uninit_in(a: A) -> Box<mem::MaybeUninit<T>, A>
where
A: AllocRef<Error = !>,
{
let Ok(b) = Self::try_new_uninit_in(a);
b
}

/// Tries to construct a new box with uninitialized contents in a specified allocator.
Expand Down Expand Up @@ -271,8 +278,12 @@ impl<T, A: AllocRef> Box<T, A> {
/// `Unpin`, then `x` will be pinned in memory and unable to be moved.
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn pin_in(x: T, a: A) -> Pin<Self> {
unsafe { Self::try_pin_in(x, a).unwrap_unchecked() }
pub fn pin_in(x: T, a: A) -> Pin<Self>
where
A: AllocRef<Error = !>,
{
let Ok(b) = Self::try_pin_in(x, a);
b
}

/// Constructs a new `Pin<Box<T, A>>` with the specified allocator. If `T` does not implement
Expand Down Expand Up @@ -314,7 +325,7 @@ impl<T> Box<[T]> {
}

#[allow(clippy::use_self)]
impl<T, A: AllocRef> Box<[T], A> {
impl<T, A: AllocRef<Error = !>> Box<[T], A> {
/// Construct a new boxed slice with uninitialized contents with the spoecified allocator.
///
/// # Example
Expand All @@ -338,9 +349,17 @@ impl<T, A: AllocRef> Box<[T], A> {
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn new_uninit_slice_in(len: usize, a: A) -> Box<[mem::MaybeUninit<T>], A> {
unsafe { Self::try_new_uninit_slice_in(len, a).unwrap_unchecked() }
match Self::try_new_uninit_slice_in(len, a) {
Ok(b) => b,
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
#[allow(unreachable_patterns)] // TODO rustc bug?
Err(CollectionAllocErr::AllocError { inner: e, .. }) => e,
}
}
}

#[allow(clippy::use_self)]
impl<T, A: AllocRef> Box<[T], A> {
/// Tries to construct a new boxed slice with uninitialized contents with the spoecified
/// allocator.
///
Expand Down Expand Up @@ -747,7 +766,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: DeallocRef> Drop for Box<T, A> {
impl<T, A> Default for Box<T, A>
where
T: Default,
A: Default + AllocRef,
A: Default + AllocRef<Error = !>,
{
#[must_use]
fn default() -> Self {
Expand All @@ -756,7 +775,7 @@ where
}

#[allow(clippy::use_self)]
impl<T, A> Default for Box<[T], A>
impl<T, A: AllocRef<Error = !>> Default for Box<[T], A>
where
A: Default + AllocRef,
{
Expand All @@ -773,7 +792,7 @@ unsafe fn from_boxed_utf8_unchecked<A: DeallocRef>(v: Box<[u8], A>) -> Box<str,
}

#[allow(clippy::use_self)]
impl<A> Default for Box<str, A>
impl<A: AllocRef<Error = !>> Default for Box<str, A>
where
A: Default + AllocRef,
{
Expand All @@ -783,7 +802,7 @@ where
}
}

impl<T: Clone, A> Clone for Box<T, A>
impl<T: Clone, A: AllocRef<Error = !>> Clone for Box<T, A>
where
A: AllocRef,
A::BuildAlloc: Clone,
Expand Down Expand Up @@ -846,7 +865,10 @@ where
impl<T: Clone, A: AllocRef, B: AllocRef> CloneIn<B> for Box<T, A> {
type Cloned = Box<T, B>;

fn clone_in(&self, a: B) -> Self::Cloned {
fn clone_in(&self, a: B) -> Self::Cloned
where
B: AllocRef<Error = !>,
{
Box::new_in(self.as_ref().clone(), a)
}

Expand Down Expand Up @@ -947,7 +969,7 @@ impl<T: ?Sized + Hasher, A: DeallocRef> Hasher for Box<T, A> {
}
}

impl<T, A> From<T> for Box<T, A>
impl<T, A: AllocRef<Error = !>> From<T> for Box<T, A>
where
A: Default + AllocRef,
{
Expand Down Expand Up @@ -983,7 +1005,7 @@ impl<T: ?Sized, A: DeallocRef> From<Box<T, A>> for Pin<Box<T, A>> {
#[allow(clippy::use_self)]
impl<T: Copy, A> From<&[T]> for Box<[T], A>
where
A: Default + AllocRef,
A: Default + AllocRef<Error = !>,
{
/// Converts a `&[T]` into a `Box<[T], B>`
///
Expand Down Expand Up @@ -1012,7 +1034,7 @@ where
#[allow(clippy::use_self)]
impl<A> From<&str> for Box<str, A>
where
A: Default + AllocRef,
A: Default + AllocRef<Error = !>,
{
/// Converts a `&str` into a `Box<str>`
///
Expand Down Expand Up @@ -1272,7 +1294,7 @@ impl_dispatch_from_dyn!(std::alloc::System);
#[allow(clippy::items_after_statements)]
impl<T: Clone, A: Clone> Clone for Box<[T], A>
where
A: AllocRef,
A: AllocRef<Error = !>,
A::BuildAlloc: Clone,
{
fn clone(&self) -> Self {
Expand Down Expand Up @@ -1383,3 +1405,10 @@ impl<F: ?Sized + Future + Unpin, A: DeallocRef> Future for Box<F, A> {
F::poll(Pin::new(&mut *self), cx)
}
}

// One central function responsible for reporting capacity overflows. This'll
// ensure that the code generation related to these panics is minimal as there's
// only one location which panics rather than a bunch throughout the module.
fn capacity_overflow() -> ! {
panic!("capacity overflow");
}
4 changes: 3 additions & 1 deletion src/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use crate::alloc::AllocRef;
pub trait CloneIn<A: AllocRef>: Sized {
type Cloned;

fn clone_in(&self, a: A) -> Self::Cloned;
fn clone_in(&self, a: A) -> Self::Cloned
where
A: AllocRef<Error = !>;

fn try_clone_in(&self, a: A) -> Result<Self::Cloned, A::Error>;
}
9 changes: 7 additions & 2 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ pub trait TryExtend<A> {
}

pub trait FromIteratorIn<T, A: AllocRef> {
fn from_iter_in<I: IntoIterator<Item = T>>(iter: I, allocator: A) -> Self;
fn from_iter_in<I: IntoIterator<Item = T>>(iter: I, allocator: A) -> Self
where
A: AllocRef<Error = !>;

fn try_from_iter_in<I: IntoIterator<Item = T>>(
iter: I,
Expand All @@ -38,7 +40,10 @@ pub trait FromIteratorIn<T, A: AllocRef> {
pub trait IteratorExt: Iterator + Sized {
#[inline]
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
fn collect_in<T: FromIteratorIn<Self::Item, A>, A: AllocRef>(self, allocator: A) -> T {
fn collect_in<T: FromIteratorIn<Self::Item, A>, A: AllocRef>(self, allocator: A) -> T
where
A: AllocRef<Error = !>,
{
FromIteratorIn::from_iter_in(self, allocator)
}

Expand Down
5 changes: 2 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
specialization,
trusted_len,
unsized_locals,
fn_traits
fn_traits,
exhaustive_patterns
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![doc(test(attr(
Expand Down Expand Up @@ -115,8 +116,6 @@ pub mod vec;

extern crate alloc as liballoc;

mod unchecked_unwrap;
use self::unchecked_unwrap::*;
pub use liballoc::{borrow, fmt, rc, slice, sync};

#[macro_export]
Expand Down
22 changes: 12 additions & 10 deletions src/raw_vec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{
alloc::{
handle_alloc_error,
AllocRef,
BuildAllocRef,
CapacityOverflow,
Expand Down Expand Up @@ -34,7 +33,6 @@ use core::{
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
/// * Guards against 32-bit systems allocating more than `isize::MAX` bytes
/// * Guards against overflowing your length
/// * Aborts on OOM or calls `handle_alloc_error` as applicable
/// * Avoids freeing `Unique::empty()`
/// * Contains a `ptr::Unique` and thus endows the user with all related benefits
///
Expand Down Expand Up @@ -164,12 +162,13 @@ impl<T, A: DeallocRef> RawVec<T, A> {
/// * on 32-bit platforms if the requested capacity exceeds `isize::MAX` bytes.
pub fn with_capacity_in(capacity: usize, a: A) -> Self
where
A: AllocRef,
A: AllocRef<Error = !>,
{
match Self::try_with_capacity_in(capacity, a) {
Ok(vec) => vec,
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
Err(CollectionAllocErr::AllocError { layout, .. }) => handle_alloc_error(layout.into()),
#[allow(unreachable_patterns)] // TODO rustc bug?
Err(CollectionAllocErr::AllocError { inner: e, .. }) => e,
}
}

Expand Down Expand Up @@ -199,12 +198,13 @@ impl<T, A: DeallocRef> RawVec<T, A> {
/// * on 32-bit platforms if the requested capacity exceeds `isize::MAX` bytes.
pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self
where
A: AllocRef,
A: AllocRef<Error = !>,
{
match Self::try_with_capacity_zeroed_in(capacity, a) {
Ok(vec) => vec,
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
Err(CollectionAllocErr::AllocError { layout, .. }) => handle_alloc_error(layout.into()),
#[allow(unreachable_patterns)] // TODO rustc bug?
Err(CollectionAllocErr::AllocError { inner: e, .. }) => e,
}
}

Expand Down Expand Up @@ -419,12 +419,13 @@ impl<T, A: DeallocRef> RawVec<T, A> {
/// ```
pub fn double(&mut self)
where
A: ReallocRef,
A: ReallocRef<Error = !>,
{
match self.try_double() {
Ok(_) => (),
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
Err(CollectionAllocErr::AllocError { layout, .. }) => handle_alloc_error(layout.into()),
#[allow(unreachable_patterns)] // TODO rustc bug?
Err(CollectionAllocErr::AllocError { inner: e, .. }) => e,
}
}

Expand Down Expand Up @@ -589,12 +590,13 @@ impl<T, A: DeallocRef> RawVec<T, A> {
/// ```
pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize)
where
A: ReallocRef,
A: ReallocRef<Error = !>,
{
match self.try_reserve(used_capacity, needed_extra_capacity) {
Ok(vec) => vec,
Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(),
Err(CollectionAllocErr::AllocError { layout, .. }) => handle_alloc_error(layout.into()),
#[allow(unreachable_patterns)] // TODO rustc bug?
Err(CollectionAllocErr::AllocError { inner: e, .. }) => e,
}
}

Expand Down
Loading

0 comments on commit 005f1b5

Please sign in to comment.