From a9a923aab81b61bf186dd62def3c268996f976a8 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 29 Nov 2019 22:57:50 -0500 Subject: [PATCH 1/9] Create PanicAdaptor --- src/alloc/mod.rs | 2 + src/alloc/panic_adaptor.rs | 95 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/alloc/panic_adaptor.rs diff --git a/src/alloc/mod.rs b/src/alloc/mod.rs index 0502890..3d97f19 100644 --- a/src/alloc/mod.rs +++ b/src/alloc/mod.rs @@ -13,6 +13,8 @@ pub use liballoc::alloc::{handle_alloc_error, Layout}; #[cfg(feature = "std")] use std::alloc::System; +mod panic_adaptor; + /// Allocate memory with the global allocator. /// /// This function forwards calls to the [`GlobalAlloc::alloc`] method diff --git a/src/alloc/panic_adaptor.rs b/src/alloc/panic_adaptor.rs new file mode 100644 index 0000000..11eb387 --- /dev/null +++ b/src/alloc/panic_adaptor.rs @@ -0,0 +1,95 @@ +//! An allocator adapter that blows up by calling `handle_alloc_error` on all errors. +//! +//! On one hand, concrete allocator implementations should always be written +//! without panicking on user error and OOM to give users maximum +//! flexibility. On the other hand, code that depends on allocation succeeding +//! should depend on `Alloc` to avoid repetitively handling errors from +//! which it cannot recover. +//! +//! This adapter bridges the gap, effectively allowing `Alloc` to be +//! implemented by any allocator. + +use core::{ptr::NonNull, usize}; + +use crate::alloc::*; + +/// An allocator adapter that blows up by calling `handle_alloc_error` on all errors. +/// +/// See the [module-level documentation](../../std/abort_adapter/index.html) for more. +#[derive(Copy, Clone, Debug, Default)] +pub struct PanicAdapter(pub Alloc); + +impl BuildAllocRef for PanicAdapter { + type Ref = PanicAdapter; + + unsafe fn build_alloc_ref( + &mut self, + ptr: NonNull, + layout: Option, + ) -> Self::Ref { + PanicAdapter(self.0.build_alloc_ref(ptr, layout)) + } +} + +impl DeallocRef for PanicAdapter { + type BuildAlloc = PanicAdapter; + + fn get_build_alloc(&mut self) -> Self::BuildAlloc { + PanicAdapter(self.0.get_build_alloc()) + } + + unsafe fn dealloc(&mut self, ptr: NonNull, layout: NonZeroLayout) { + self.0.dealloc(ptr, layout) + } +} + +impl AllocRef for PanicAdapter { + type Error = !; + + fn alloc(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { + self.0 + .alloc(layout) + .or_else(|_| handle_alloc_error(layout.into())) + } + + fn alloc_zeroed(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { + self.0 + .alloc_zeroed(layout) + .or_else(|_| handle_alloc_error(layout.into())) + } + + fn usable_size(&self, layout: NonZeroLayout) -> (usize, usize) { + self.0.usable_size(layout) + } + + unsafe fn grow_in_place( + &mut self, + ptr: NonNull, + layout: NonZeroLayout, + new_size: NonZeroUsize, + ) -> bool { + self.0.grow_in_place(ptr, layout, new_size) + } + + unsafe fn shrink_in_place( + &mut self, + ptr: NonNull, + layout: NonZeroLayout, + new_size: NonZeroUsize, + ) -> bool { + self.0.shrink_in_place(ptr, layout, new_size) + } +} + +impl ReallocRef for PanicAdapter { + unsafe fn realloc( + &mut self, + ptr: NonNull, + old_layout: NonZeroLayout, + new_layout: NonZeroLayout, + ) -> Result, Self::Error> { + self.0 + .realloc(ptr, old_layout, new_layout) + .or_else(|_| handle_alloc_error(new_layout.into())) + } +} From 8a1087207df1b69f267195b9cc108a0d80265bfb Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 00:56:41 -0500 Subject: [PATCH 2/9] Switch defaults to PanicHandler --- src/alloc/mod.rs | 1 + src/boxed.rs | 12 ++++++------ src/raw_vec.rs | 11 ++++++----- src/string.rs | 12 ++++++------ src/vec.rs | 33 ++++++++++++++++++++++----------- 5 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/alloc/mod.rs b/src/alloc/mod.rs index 3d97f19..496438a 100644 --- a/src/alloc/mod.rs +++ b/src/alloc/mod.rs @@ -14,6 +14,7 @@ pub use liballoc::alloc::{handle_alloc_error, Layout}; use std::alloc::System; mod panic_adaptor; +pub use self::panic_adaptor::PanicAdapter; /// Allocate memory with the global allocator. /// diff --git a/src/boxed.rs b/src/boxed.rs index 074c91d..50b3f66 100644 --- a/src/boxed.rs +++ b/src/boxed.rs @@ -79,7 +79,7 @@ //! [`NonZeroLayout::for_value(&*value)`]: crate::alloc::NonZeroLayout::for_value use crate::{ - alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout}, + alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout, PanicAdapter}, clone::CloneIn, collections::CollectionAllocErr, raw_vec::RawVec, @@ -105,7 +105,7 @@ use core::{ /// A pointer type for heap allocation. /// /// See the [module-level documentation](index.html) for more. -pub struct Box { +pub struct Box> { ptr: Unique, build_alloc: A::BuildAlloc, } @@ -131,7 +131,7 @@ impl Box { #[inline(always)] #[must_use] pub fn new(x: T) -> Self { - Self::new_in(x, Global) + Self::new_in(x, PanicAdapter(Global)) } /// Constructs a new box with uninitialized contents. @@ -156,7 +156,7 @@ impl Box { #[inline(always)] #[must_use] pub fn new_uninit() -> Box> { - Self::new_uninit_in(Global) + Self::new_uninit_in(PanicAdapter(Global)) } /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then @@ -309,7 +309,7 @@ impl Box<[T]> { #[inline(always)] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - Self::new_uninit_slice_in(len, Global) + Self::new_uninit_slice_in(len, PanicAdapter(Global)) } } @@ -503,7 +503,7 @@ impl Box { #[allow(clippy::inline_always)] #[inline(always)] pub unsafe fn from_raw(raw: *mut T) -> Self { - Self::from_raw_in(raw, Global) + Self::from_raw_in(raw, PanicAdapter(Global)) } } diff --git a/src/raw_vec.rs b/src/raw_vec.rs index 3cc236c..4d7b153 100644 --- a/src/raw_vec.rs +++ b/src/raw_vec.rs @@ -7,6 +7,7 @@ use crate::{ DeallocRef, Global, NonZeroLayout, + PanicAdapter, ReallocRef, }, boxed::Box, @@ -51,7 +52,7 @@ use core::{ /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. // Using `NonNull` + `PhantomData` instead of `Unique` to stay on stable as long as possible -pub struct RawVec { +pub struct RawVec> { ptr: Unique, capacity: usize, build_alloc: A::BuildAlloc, @@ -89,7 +90,7 @@ impl RawVec { ptr: Unique::empty(), // FIXME(mark-i-m): use `cap` when ifs are allowed in const capacity: [0, !0][(mem::size_of::() == 0) as usize], - build_alloc: Global, + build_alloc: PanicAdapter(Global), } } @@ -110,7 +111,7 @@ impl RawVec { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + Self::with_capacity_in(capacity, PanicAdapter(Global)) } /// Like `with_capacity`, but guarantees the buffer is zeroed. @@ -126,7 +127,7 @@ impl RawVec { #[inline] #[must_use] pub fn with_capacity_zeroed(capacity: usize) -> Self { - Self::with_capacity_zeroed_in(capacity, Global) + Self::with_capacity_zeroed_in(capacity, PanicAdapter(Global)) } /// Reconstitutes a `RawVec` from a pointer, and capacity. @@ -138,7 +139,7 @@ impl RawVec { /// If the ptr and capacity come from a `RawVec` created with `Global`, then this is guaranteed. #[inline] pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { - Self::from_raw_parts_in(ptr, capacity, Global) + Self::from_raw_parts_in(ptr, capacity, PanicAdapter(Global)) } } diff --git a/src/string.rs b/src/string.rs index 980f798..8781f64 100644 --- a/src/string.rs +++ b/src/string.rs @@ -52,7 +52,7 @@ //! ``` use crate::{ - alloc::{AllocRef, DeallocRef, Global, ReallocRef}, + alloc::{AllocRef, DeallocRef, Global, PanicAdapter, ReallocRef}, boxed::Box, collections::CollectionAllocErr, iter::TryExtend, @@ -312,7 +312,7 @@ pub use liballoc::string::{ParseError, ToString}; /// [`Deref`]: ../../std/ops/trait.Deref.html /// [`as_str()`]: struct.String.html#method.as_str #[derive(PartialOrd, Eq, Ord)] -pub struct String { +pub struct String> { vec: Vec, } @@ -354,7 +354,7 @@ pub struct String { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[derive(Debug)] -pub struct FromUtf8Error { +pub struct FromUtf8Error> { bytes: Vec, error: Utf8Error, } @@ -451,7 +451,7 @@ impl String { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + Self::with_capacity_in(capacity, PanicAdapter(Global)) } /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] @@ -475,7 +475,7 @@ impl String { /// assert!(String::from_utf16(v).is_err()); /// ``` pub fn from_utf16(v: &[u16]) -> Result { - Self::from_utf16_in(v, Global) + Self::from_utf16_in(v, PanicAdapter(Global)) } /// Decode a UTF-16 encoded slice `v` into a `String`, replacing @@ -560,7 +560,7 @@ impl String { /// ``` #[inline] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> Self { - Self::from_raw_parts_in(buf, length, capacity, Global) + Self::from_raw_parts_in(buf, length, capacity, PanicAdapter(Global)) } } diff --git a/src/vec.rs b/src/vec.rs index 50b7b45..d065af5 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -69,7 +69,15 @@ //! [`vec!`]: ../macro.vec.html use crate::{ - alloc::{handle_alloc_error, AllocRef, BuildAllocRef, DeallocRef, Global, ReallocRef}, + alloc::{ + handle_alloc_error, + AllocRef, + BuildAllocRef, + DeallocRef, + Global, + PanicAdapter, + ReallocRef, + }, boxed::Box, clone::CloneIn, collections::CollectionAllocErr, @@ -328,7 +336,7 @@ use core::{ /// [`insert`]: Self::insert() /// [`reserve`]: Self::reserve /// [owned slice]: crate::boxed::Box -pub struct Vec { +pub struct Vec> { buf: RawVec, len: usize, } @@ -401,7 +409,7 @@ impl Vec { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + Self::with_capacity_in(capacity, PanicAdapter(Global)) } /// Creates a `Vec` directly from the raw components of another vector. @@ -664,7 +672,7 @@ impl Vec { /// # Examples /// /// ``` - /// use alloc_wg::{alloc::Global, collections::CollectionAllocErr, vec::Vec}; + /// use alloc_wg::{alloc::PanicAdapter, collections::CollectionAllocErr, vec::Vec}; /// /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { /// let mut output = Vec::new(); @@ -2024,7 +2032,7 @@ impl Vec { #[doc(hidden)] pub fn from_elem(elem: T, n: usize) -> Vec { - from_elem_in(elem, n, Global) + from_elem_in(elem, n, PanicAdapter(Global)) } #[doc(hidden)] @@ -2267,7 +2275,10 @@ impl FromIterator for Vec { #[inline] #[must_use] fn from_iter>(iter: I) -> Self { - >::from_iter_in(iter.into_iter(), Global) + >>::from_iter_in( + iter.into_iter(), + PanicAdapter(Global), + ) } } @@ -2896,7 +2907,7 @@ impl From<&str> for Vec { /// /// [`Vec`]: struct.Vec.html /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html -pub struct IntoIter { +pub struct IntoIter> { buf: RawVec, ptr: *const T, end: *const T, @@ -3042,7 +3053,7 @@ impl Drop for IntoIter { /// /// [`drain`]: struct.Vec.html#method.drain /// [`Vec`]: struct.Vec.html -pub struct Drain<'a, T, A: DeallocRef = Global> { +pub struct Drain<'a, T, A: DeallocRef = PanicAdapter> { /// Index of tail to preserve tail_start: usize, /// Length of tail @@ -3135,7 +3146,7 @@ impl FusedIterator for Drain<'_, T, A> {} /// [`splice()`]: struct.Vec.html#method.splice /// [`Vec`]: struct.Vec.html #[derive(Debug)] -pub struct Splice<'a, I: Iterator + 'a, A = Global> +pub struct Splice<'a, I: Iterator + 'a, A = PanicAdapter> where A: ReallocRef, { @@ -3257,7 +3268,7 @@ where /// An iterator produced by calling `drain_filter` on Vec. // #[derive(Debug)] -pub struct DrainFilter<'a, T, F, A: DeallocRef = Global> +pub struct DrainFilter<'a, T, F, A: DeallocRef = PanicAdapter> where F: FnMut(&mut T) -> bool, { @@ -3320,7 +3331,7 @@ where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: DeallocRef = Global> + struct BackshiftOnDrop<'a, 'b, T, F, A: DeallocRef = PanicAdapter> where F: FnMut(&mut T) -> bool, { From 526c44e775be7c5578d720f2942f84fbd78523cb Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 00:56:41 -0500 Subject: [PATCH 3/9] Require Error = ! for "infallible allocation --- src/boxed.rs | 65 +++++++++++++++------- src/clone.rs | 4 +- src/iter.rs | 9 +++- src/lib.rs | 5 +- src/raw_vec.rs | 22 ++++---- src/string.rs | 73 ++++++++++++++----------- src/unchecked_unwrap.rs | 62 --------------------- src/vec.rs | 116 +++++++++++++++++++++++----------------- 8 files changed, 179 insertions(+), 177 deletions(-) delete mode 100644 src/unchecked_unwrap.rs diff --git a/src/boxed.rs b/src/boxed.rs index 50b3f66..f5daf72 100644 --- a/src/boxed.rs +++ b/src/boxed.rs @@ -83,7 +83,6 @@ use crate::{ clone::CloneIn, collections::CollectionAllocErr, raw_vec::RawVec, - UncheckedResultExt, }; use core::{ any::Any, @@ -184,8 +183,12 @@ impl Box { /// ``` #[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, + { + let Ok(b) = Self::try_new_in(x, a); + b } /// Tries to allocate memory with the given allocator and then places `x` into it. @@ -234,8 +237,12 @@ impl Box { /// ``` #[allow(clippy::inline_always)] #[inline(always)] - pub fn new_uninit_in(a: A) -> Box, A> { - unsafe { Self::try_new_uninit_in(a).unwrap_unchecked() } + pub fn new_uninit_in(a: A) -> Box, A> + where + A: AllocRef, + { + let Ok(b) = Self::try_new_uninit_in(a); + b } /// Tries to construct a new box with uninitialized contents in a specified allocator. @@ -271,8 +278,12 @@ impl Box { /// `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 { - unsafe { Self::try_pin_in(x, a).unwrap_unchecked() } + pub fn pin_in(x: T, a: A) -> Pin + where + A: AllocRef, + { + let Ok(b) = Self::try_pin_in(x, a); + b } /// Constructs a new `Pin>` with the specified allocator. If `T` does not implement @@ -314,7 +325,7 @@ impl Box<[T]> { } #[allow(clippy::use_self)] -impl Box<[T], A> { +impl> Box<[T], A> { /// Construct a new boxed slice with uninitialized contents with the spoecified allocator. /// /// # Example @@ -338,9 +349,17 @@ impl Box<[T], A> { #[allow(clippy::inline_always)] #[inline(always)] pub fn new_uninit_slice_in(len: usize, a: A) -> Box<[mem::MaybeUninit], 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 Box<[T], A> { /// Tries to construct a new boxed slice with uninitialized contents with the spoecified /// allocator. /// @@ -747,7 +766,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: DeallocRef> Drop for Box { impl Default for Box where T: Default, - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -756,7 +775,7 @@ where } #[allow(clippy::use_self)] -impl Default for Box<[T], A> +impl> Default for Box<[T], A> where A: Default + AllocRef, { @@ -773,7 +792,7 @@ unsafe fn from_boxed_utf8_unchecked(v: Box<[u8], A>) -> Box Default for Box +impl> Default for Box where A: Default + AllocRef, { @@ -783,7 +802,7 @@ where } } -impl Clone for Box +impl> Clone for Box where A: AllocRef, A::BuildAlloc: Clone, @@ -846,7 +865,10 @@ where impl CloneIn for Box { type Cloned = Box; - fn clone_in(&self, a: B) -> Self::Cloned { + fn clone_in(&self, a: B) -> Self::Cloned + where + B: AllocRef, + { Box::new_in(self.as_ref().clone(), a) } @@ -947,7 +969,7 @@ impl Hasher for Box { } } -impl From for Box +impl> From for Box where A: Default + AllocRef, { @@ -983,7 +1005,7 @@ impl From> for Pin> { #[allow(clippy::use_self)] impl From<&[T]> for Box<[T], A> where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a `&[T]` into a `Box<[T], B>` /// @@ -1012,7 +1034,7 @@ where #[allow(clippy::use_self)] impl From<&str> for Box where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a `&str` into a `Box` /// @@ -1272,7 +1294,7 @@ impl_dispatch_from_dyn!(std::alloc::System); #[allow(clippy::items_after_statements)] impl Clone for Box<[T], A> where - A: AllocRef, + A: AllocRef, A::BuildAlloc: Clone, { fn clone(&self) -> Self { @@ -1383,3 +1405,10 @@ impl Future for Box { 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"); +} diff --git a/src/clone.rs b/src/clone.rs index 1fbe118..18b43d5 100644 --- a/src/clone.rs +++ b/src/clone.rs @@ -3,7 +3,9 @@ use crate::alloc::AllocRef; pub trait CloneIn: Sized { type Cloned; - fn clone_in(&self, a: A) -> Self::Cloned; + fn clone_in(&self, a: A) -> Self::Cloned + where + A: AllocRef; fn try_clone_in(&self, a: A) -> Result; } diff --git a/src/iter.rs b/src/iter.rs index 591701f..2b5b2ce 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -25,7 +25,9 @@ pub trait TryExtend { } pub trait FromIteratorIn { - fn from_iter_in>(iter: I, allocator: A) -> Self; + fn from_iter_in>(iter: I, allocator: A) -> Self + where + A: AllocRef; fn try_from_iter_in>( iter: I, @@ -38,7 +40,10 @@ pub trait FromIteratorIn { pub trait IteratorExt: Iterator + Sized { #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] - fn collect_in, A: AllocRef>(self, allocator: A) -> T { + fn collect_in, A: AllocRef>(self, allocator: A) -> T + where + A: AllocRef, + { FromIteratorIn::from_iter_in(self, allocator) } diff --git a/src/lib.rs b/src/lib.rs index 0f49cd4..a3b5762 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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( @@ -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] diff --git a/src/raw_vec.rs b/src/raw_vec.rs index 4d7b153..7378798 100644 --- a/src/raw_vec.rs +++ b/src/raw_vec.rs @@ -1,6 +1,5 @@ use crate::{ alloc::{ - handle_alloc_error, AllocRef, BuildAllocRef, CapacityOverflow, @@ -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 /// @@ -164,12 +162,13 @@ impl RawVec { /// * 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, { 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, } } @@ -199,12 +198,13 @@ impl RawVec { /// * 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, { 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, } } @@ -419,12 +419,13 @@ impl RawVec { /// ``` pub fn double(&mut self) where - A: ReallocRef, + A: ReallocRef, { 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, } } @@ -589,12 +590,13 @@ impl RawVec { /// ``` pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { 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, } } diff --git a/src/string.rs b/src/string.rs index 8781f64..90836c3 100644 --- a/src/string.rs +++ b/src/string.rs @@ -80,7 +80,7 @@ use core::{ #[cfg(feature = "std")] use std::borrow::Cow; -use crate::{alloc::handle_alloc_error, clone::CloneIn}; +use crate::clone::CloneIn; pub use liballoc::string::{ParseError, ToString}; /// A UTF-8 encoded, growable string. @@ -580,10 +580,13 @@ impl String { #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self where - A: AllocRef, + A: AllocRef, { - Self { - vec: Vec::with_capacity_in(capacity, a), + match Self::try_with_capacity_in(capacity, a) { + Ok(vec) => vec, + Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(), + #[allow(unreachable_patterns)] // TODO rustc bug? + Err(CollectionAllocErr::AllocError { inner: e, .. }) => e, } } @@ -605,7 +608,7 @@ impl String { #[inline] pub fn from_str_in(s: &str, a: A) -> Self where - A: ReallocRef, + A: ReallocRef, { let mut v = Self::with_capacity_in(s.len(), a); v.push_str(s); @@ -705,12 +708,13 @@ impl String { /// Panics if allocation fails. pub fn from_utf8_lossy_in(v: &[u8], a: A) -> Self where - A: ReallocRef, + A: ReallocRef, { match Self::try_from_utf8_lossy_in(v, a) { Ok(s) => s, 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, } } @@ -753,7 +757,7 @@ impl String { /// Like `from_utf16` but parameterized over the choice of allocator for the returned `String`. pub fn from_utf16_in(v: &[u16], a: A) -> Result where - A: ReallocRef, + A: ReallocRef, { // This isn't done via collect::>() for performance reasons. // FIXME: the function can be simplified again when #48994 is closed. @@ -928,7 +932,7 @@ impl String { #[inline] pub fn push_str(&mut self, string: &str) where - A: ReallocRef, + A: ReallocRef, { self.vec.extend_from_slice(string.as_bytes()) } @@ -1012,7 +1016,7 @@ impl String { #[inline] pub fn reserve(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.reserve(additional) } @@ -1251,12 +1255,13 @@ impl String { #[inline] pub fn push(&mut self, ch: char) where - A: ReallocRef, + A: ReallocRef, { match self.try_push(ch) { Ok(s) => s, 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, } } @@ -1503,12 +1508,13 @@ impl String { #[inline] pub fn insert(&mut self, idx: usize, ch: char) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert(idx, ch) { Ok(s) => s, 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, } } @@ -1578,12 +1584,13 @@ impl String { #[inline] pub fn insert_str(&mut self, idx: usize, string: &str) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert_str(idx, string) { Ok(s) => s, 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, } } @@ -1701,12 +1708,13 @@ impl String { #[inline] pub fn split_off(&mut self, at: usize) -> Self where - A: AllocRef, + A: AllocRef, { match self.try_split_off(at) { Ok(s) => s, 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, } } @@ -1819,7 +1827,7 @@ impl String { /// # Panics /// /// Panics if the starting point or end point do not lie on a [`char`] - /// boundary, or if they're out of bounds. + /// boundary, or if they're out of bounds, or if there is an allocation failure /// /// [`char`]: ../../std/primitive.char.html /// [`Vec::splice`]: ../../std/vec/struct.Vec.html#method.splice @@ -1840,7 +1848,7 @@ impl String { pub fn replace_range(&mut self, range: R, replace_with: &str) where R: RangeBounds, - A: ReallocRef, + A: ReallocRef, { // Memory safety // @@ -1885,7 +1893,7 @@ impl String { #[inline] pub fn into_boxed_str(self) -> Box where - A: ReallocRef, + A: ReallocRef, { let slice = self.vec.into_boxed_slice(); unsafe { from_boxed_utf8_unchecked(slice) } @@ -1991,7 +1999,7 @@ impl fmt::Display for FromUtf16Error { } } -impl Clone for String +impl> Clone for String where A: AllocRef, A::BuildAlloc: Clone, @@ -2015,7 +2023,10 @@ impl CloneIn for String { #[inline] #[must_use = "Cloning is expected to be expensive"] - fn clone_in(&self, a: B) -> Self::Cloned { + fn clone_in(&self, a: B) -> Self::Cloned + where + B: AllocRef, + { String { vec: self.vec.clone_in(a), } @@ -2091,7 +2102,7 @@ impl<'a> FromIterator> for String { impl Extend for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { let iterator = iter.into_iter(); @@ -2115,7 +2126,7 @@ impl TryExtend for String { impl<'a, A> Extend<&'a char> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); @@ -2132,7 +2143,7 @@ impl<'a, A: ReallocRef> TryExtend<&'a char> for String { impl<'a, A> Extend<&'a str> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); @@ -2149,7 +2160,7 @@ impl<'a, A: ReallocRef> TryExtend<&'a str> for String { impl Extend> for String where - A: ReallocRef, + A: ReallocRef, B: DeallocRef, { fn extend>>(&mut self, iter: I) { @@ -2169,7 +2180,7 @@ impl TryExtend> for String { #[cfg(feature = "std")] impl<'a, A> Extend> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); @@ -2305,7 +2316,7 @@ impl hash::Hash for String { /// ``` impl Add<&str> for String where - A: ReallocRef, + A: ReallocRef, { type Output = Self; @@ -2321,7 +2332,7 @@ where /// This has the same behavior as the [`push_str`][`String::push_str`] method. impl AddAssign<&str> for String where - A: ReallocRef, + A: ReallocRef, { #[inline] fn add_assign(&mut self, other: &str) { @@ -2497,7 +2508,7 @@ impl From> for String { impl From> for Box where - A: ReallocRef, + A: ReallocRef, { /// Converts the given `String` to a boxed `str` slice that is owned. /// diff --git a/src/unchecked_unwrap.rs b/src/unchecked_unwrap.rs deleted file mode 100644 index f9f75a0..0000000 --- a/src/unchecked_unwrap.rs +++ /dev/null @@ -1,62 +0,0 @@ -use core::hint::unreachable_unchecked; - -/// An extension trait for `Option` providing unchecked unwrapping. -pub trait UncheckedOptionExt { - /// Unwraps an `Option`, yielding the content of a [`Some`][]. - /// - /// # Safety - /// - /// The `Option` has to be `Some` - unsafe fn unwrap_unchecked(self) -> T; - - /// Unwraps an `Option`, expecting [`None`][] and returning nothing. - /// - /// # Safety - /// - /// The `Option` has to be `None`. - unsafe fn unwrap_none_unchecked(self); -} - -/// An extension trait for `Result` providing unchecked unwrapping. -pub trait UncheckedResultExt { - /// Unwraps a `Result`, yielding the content of an [`Ok`][]. - /// - /// # Safety - /// - /// The `Result` has to be `Ok` - unsafe fn unwrap_unchecked(self) -> T; - - /// Unwraps a `Result`, yielding the content of an [`Err`][]. - /// - /// # Safety - /// - /// The `Result` has to be `Err`. - unsafe fn unwrap_err_unchecked(self) -> E; -} - -unsafe fn unreachable() -> ! { - debug_assert!(false); - unreachable_unchecked() -} - -impl UncheckedOptionExt for Option { - unsafe fn unwrap_unchecked(self) -> T { - if let Some(t) = self { t } else { unreachable() } - } - - unsafe fn unwrap_none_unchecked(self) { - if self.is_some() { - unreachable() - } - } -} - -impl UncheckedResultExt for Result { - unsafe fn unwrap_unchecked(self) -> T { - if let Ok(t) = self { t } else { unreachable() } - } - - unsafe fn unwrap_err_unchecked(self) -> E { - if let Err(t) = self { t } else { unreachable() } - } -} diff --git a/src/vec.rs b/src/vec.rs index d065af5..1096948 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -69,15 +69,7 @@ //! [`vec!`]: ../macro.vec.html use crate::{ - alloc::{ - handle_alloc_error, - AllocRef, - BuildAllocRef, - DeallocRef, - Global, - PanicAdapter, - ReallocRef, - }, + alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, PanicAdapter, ReallocRef}, boxed::Box, clone::CloneIn, collections::CollectionAllocErr, @@ -498,7 +490,7 @@ impl Vec { #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self where - A: AllocRef, + A: AllocRef, { Self { buf: RawVec::with_capacity_in(capacity, a), @@ -620,7 +612,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn reserve(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.reserve(self.len, additional); } @@ -852,12 +844,13 @@ impl Vec { /// Panics if the reallocation fails. pub fn into_boxed_slice(self) -> Box<[T], A> where - A: ReallocRef, + A: ReallocRef, { match self.try_into_boxed_slice() { 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, } } @@ -1196,12 +1189,13 @@ impl Vec { /// ``` pub fn insert(&mut self, index: usize, element: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert(index, element) { 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, } } @@ -1385,12 +1379,13 @@ impl Vec { #[inline] pub fn push(&mut self, value: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_push(value) { 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, } } @@ -1470,12 +1465,13 @@ impl Vec { #[inline] pub fn append(&mut self, other: &mut Self) where - A: ReallocRef, + A: ReallocRef, { match self.try_append(other) { 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, } } @@ -1655,12 +1651,13 @@ impl Vec { #[inline] pub fn split_off(&mut self, at: usize) -> Self where - A: AllocRef, + A: AllocRef, { match self.try_split_off(at) { 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, } } @@ -1725,12 +1722,13 @@ impl Vec { pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T, - A: ReallocRef, + A: ReallocRef, { match self.try_resize_with(new_len, f) { 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, } } @@ -1779,7 +1777,7 @@ impl Vec { pub fn leak<'a>(vec: Self) -> &'a mut [T] where T: 'a, // Technically not needed, but kept to be explicit. - A: ReallocRef, + A: ReallocRef, { Box::leak(vec.into_boxed_slice()) } @@ -1826,11 +1824,15 @@ impl Vec { /// # Panics /// /// Panics if the reallocation fails. - pub fn resize(&mut self, new_len: usize, value: T) { + pub fn resize(&mut self, new_len: usize, value: T) + where + A: AllocRef, + { match self.try_resize(new_len, value) { 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, } } @@ -1870,7 +1872,10 @@ impl Vec { /// # Panics /// /// Panics if the reallocation fails. - pub fn extend_from_slice(&mut self, other: &[T]) { + pub fn extend_from_slice(&mut self, other: &[T]) + where + A: AllocRef, + { self.spec_extend(other.iter()) } @@ -2038,12 +2043,13 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[doc(hidden)] pub fn from_elem_in(elem: T, n: usize, a: A) -> Vec where - A: ReallocRef, + A: ReallocRef, { match try_from_elem_in(elem, n, 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, } } @@ -2185,7 +2191,7 @@ unsafe impl IsZero for Option> { // Common trait implementations for Vec //////////////////////////////////////////////////////////////////////////////// -impl Clone for Vec +impl> Clone for Vec where A: AllocRef, A::BuildAlloc: Clone, @@ -2208,12 +2214,11 @@ where impl CloneIn for Vec { type Cloned = Vec; - fn clone_in(&self, a: B) -> Self::Cloned { - let mut v = Vec::with_capacity_in(self.len(), a); - - self.iter() - .cloned() - .for_each(|element| unsafe { v.push_unchecked(element) }); + fn clone_in(&self, a: B) -> Self::Cloned + where + B: AllocRef, + { + let Ok(v) = self.try_clone_in(a); v } @@ -2285,7 +2290,10 @@ impl FromIterator for Vec { impl FromIteratorIn for Vec { #[inline] #[must_use] - fn from_iter_in>(iter: I, a: A) -> Self { + fn from_iter_in>(iter: I, a: A) -> Self + where + A: AllocRef, + { >::from_iter_in(iter.into_iter(), a) } @@ -2360,7 +2368,7 @@ impl<'a, T, A: DeallocRef> IntoIterator for &'a mut Vec { impl Extend for Vec where - A: ReallocRef, + A: ReallocRef, { #[inline] fn extend>(&mut self, iter: I) { @@ -2379,22 +2387,30 @@ impl TryExtend for Vec { trait SpecExtend: Sized { #[inline] - fn from_iter_in(iter: I, a: A) -> Self { + fn from_iter_in(iter: I, a: A) -> Self + where + A: AllocRef, + { match Self::try_from_iter_in(iter, a) { Ok(v) => v, 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, } } fn try_from_iter_in(iter: I, a: A) -> Result>; #[inline] - fn spec_extend(&mut self, iter: I) { + fn spec_extend(&mut self, iter: I) + where + A: AllocRef, + { match self.try_spec_extend(iter) { 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, } } @@ -2601,7 +2617,7 @@ impl Vec { #[inline] pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> where - A: ReallocRef, + A: ReallocRef, R: RangeBounds, I: IntoIterator, { @@ -2689,7 +2705,7 @@ impl Vec { /// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice impl<'a, T: 'a + Copy, A> Extend<&'a T> for Vec where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()) @@ -3148,7 +3164,7 @@ impl FusedIterator for Drain<'_, T, A> {} #[derive(Debug)] pub struct Splice<'a, I: Iterator + 'a, A = PanicAdapter> where - A: ReallocRef, + A: ReallocRef, // Because Drop can allocate { drain: Drain<'a, I::Item, A>, replace_with: I, @@ -3156,7 +3172,7 @@ where impl Iterator for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { type Item = I::Item; @@ -3171,18 +3187,18 @@ where impl DoubleEndedIterator for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { fn next_back(&mut self) -> Option { self.drain.next_back() } } -impl ExactSizeIterator for Splice<'_, I, A> where A: ReallocRef {} +impl ExactSizeIterator for Splice<'_, I, A> where A: ReallocRef {} impl Drop for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { fn drop(&mut self) { self.drain.by_ref().for_each(drop); @@ -3228,7 +3244,7 @@ where /// Private helper methods for `Splice::drop` impl Drain<'_, T, A> where - A: ReallocRef, + A: ReallocRef, { /// The range from `self.vec.len` to `self.tail_start` contains elements /// that have been moved out. From 91d44ee3e357f2afaf6b65d4fb25b966fd7dcfdd Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 09:37:57 -0500 Subject: [PATCH 4/9] Revert "Revert tests for `string` and `vec`" This reverts commit 0ab26631a097ae208928ae3b5e29276233f7f228. --- tests/string.rs | 23 ++++++++++++++++++----- tests/vec.rs | 17 +++++++++++------ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/string.rs b/tests/string.rs index d43ac4e..7fc5731 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -1,4 +1,11 @@ -use alloc_wg::{borrow::Cow, collections::CollectionAllocErr::*, string::String, vec, vec::Vec}; +use alloc_wg::{ + alloc::Global, + borrow::Cow, + collections::CollectionAllocErr::*, + string::String, + vec, + vec::Vec, +}; use core::{isize, mem::size_of, usize}; pub trait IntoCow<'a, B: ?Sized> @@ -576,7 +583,7 @@ fn test_try_reserve() { { // Note: basic stuff is checked by test_reserve - let mut empty_string = String::new(); + let mut empty_string = String::new_in(Global); // Check isize::MAX doesn't count as an overflow if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { @@ -616,7 +623,10 @@ fn test_try_reserve() { { // Same basic idea, but with non-zero len - let mut ten_bytes = String::from("0123456789"); + let mut ten_bytes = String::new_in(Global); + ten_bytes + .try_push_str("0123456789") + .expect("Could not create string with 10 bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -655,7 +665,7 @@ fn test_try_reserve_exact() { let guards_against_isize = size_of::() < 8; { - let mut empty_string = String::new(); + let mut empty_string = String::new_in(Global); if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -688,7 +698,10 @@ fn test_try_reserve_exact() { } { - let mut ten_bytes = String::from("0123456789"); + let mut ten_bytes = String::new_in(Global); + ten_bytes + .try_push_str("0123456789") + .expect("Could not create string with 10 bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); diff --git a/tests/vec.rs b/tests/vec.rs index 0cb43b6..ec4d189 100644 --- a/tests/vec.rs +++ b/tests/vec.rs @@ -1,4 +1,5 @@ use alloc_wg::{ + alloc::Global, boxed::Box, collections::CollectionAllocErr::*, vec, @@ -1125,7 +1126,7 @@ fn test_try_reserve() { { // Note: basic stuff is checked by test_reserve - let mut empty_bytes: Vec = Vec::new(); + let mut empty_bytes: Vec = Vec::new_in(Global); // Check isize::MAX doesn't count as an overflow if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { @@ -1163,7 +1164,8 @@ fn test_try_reserve() { { // Same basic idea, but with non-zero len - let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_bytes: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate ten bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1188,7 +1190,8 @@ fn test_try_reserve() { { // Same basic idea, but with interesting type size - let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_u32s: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate 40 bytes"); if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1225,7 +1228,7 @@ fn test_try_reserve_exact() { let guards_against_isize = size_of::() < 8; { - let mut empty_bytes: Vec = Vec::new(); + let mut empty_bytes: Vec = Vec::new_in(Global); if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1256,7 +1259,8 @@ fn test_try_reserve_exact() { } { - let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_bytes: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate ten bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1279,7 +1283,8 @@ fn test_try_reserve_exact() { } { - let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_u32s: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate 40 bytes"); if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); From c693213c66aef8c6feb1c266daf26285f13f2a4f Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 09:51:10 -0500 Subject: [PATCH 5/9] Use old name --- src/alloc/mod.rs | 2 +- src/alloc/panic_adaptor.rs | 18 +++++++++--------- src/boxed.rs | 12 ++++++------ src/raw_vec.rs | 12 ++++++------ src/string.rs | 12 ++++++------ src/vec.rs | 24 ++++++++++++------------ 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/alloc/mod.rs b/src/alloc/mod.rs index 496438a..43e3c4f 100644 --- a/src/alloc/mod.rs +++ b/src/alloc/mod.rs @@ -14,7 +14,7 @@ pub use liballoc::alloc::{handle_alloc_error, Layout}; use std::alloc::System; mod panic_adaptor; -pub use self::panic_adaptor::PanicAdapter; +pub use self::panic_adaptor::AbortAlloc; /// Allocate memory with the global allocator. /// diff --git a/src/alloc/panic_adaptor.rs b/src/alloc/panic_adaptor.rs index 11eb387..e067545 100644 --- a/src/alloc/panic_adaptor.rs +++ b/src/alloc/panic_adaptor.rs @@ -17,25 +17,25 @@ use crate::alloc::*; /// /// See the [module-level documentation](../../std/abort_adapter/index.html) for more. #[derive(Copy, Clone, Debug, Default)] -pub struct PanicAdapter(pub Alloc); +pub struct AbortAlloc(pub Alloc); -impl BuildAllocRef for PanicAdapter { - type Ref = PanicAdapter; +impl BuildAllocRef for AbortAlloc { + type Ref = AbortAlloc; unsafe fn build_alloc_ref( &mut self, ptr: NonNull, layout: Option, ) -> Self::Ref { - PanicAdapter(self.0.build_alloc_ref(ptr, layout)) + AbortAlloc(self.0.build_alloc_ref(ptr, layout)) } } -impl DeallocRef for PanicAdapter { - type BuildAlloc = PanicAdapter; +impl DeallocRef for AbortAlloc { + type BuildAlloc = AbortAlloc; fn get_build_alloc(&mut self) -> Self::BuildAlloc { - PanicAdapter(self.0.get_build_alloc()) + AbortAlloc(self.0.get_build_alloc()) } unsafe fn dealloc(&mut self, ptr: NonNull, layout: NonZeroLayout) { @@ -43,7 +43,7 @@ impl DeallocRef for PanicAdapter { } } -impl AllocRef for PanicAdapter { +impl AllocRef for AbortAlloc { type Error = !; fn alloc(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { @@ -81,7 +81,7 @@ impl AllocRef for PanicAdapter { } } -impl ReallocRef for PanicAdapter { +impl ReallocRef for AbortAlloc { unsafe fn realloc( &mut self, ptr: NonNull, diff --git a/src/boxed.rs b/src/boxed.rs index f5daf72..5f37050 100644 --- a/src/boxed.rs +++ b/src/boxed.rs @@ -79,7 +79,7 @@ //! [`NonZeroLayout::for_value(&*value)`]: crate::alloc::NonZeroLayout::for_value use crate::{ - alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout, PanicAdapter}, + alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout, AbortAlloc}, clone::CloneIn, collections::CollectionAllocErr, raw_vec::RawVec, @@ -104,7 +104,7 @@ use core::{ /// A pointer type for heap allocation. /// /// See the [module-level documentation](index.html) for more. -pub struct Box> { +pub struct Box> { ptr: Unique, build_alloc: A::BuildAlloc, } @@ -130,7 +130,7 @@ impl Box { #[inline(always)] #[must_use] pub fn new(x: T) -> Self { - Self::new_in(x, PanicAdapter(Global)) + Self::new_in(x, AbortAlloc(Global)) } /// Constructs a new box with uninitialized contents. @@ -155,7 +155,7 @@ impl Box { #[inline(always)] #[must_use] pub fn new_uninit() -> Box> { - Self::new_uninit_in(PanicAdapter(Global)) + Self::new_uninit_in(AbortAlloc(Global)) } /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then @@ -320,7 +320,7 @@ impl Box<[T]> { #[inline(always)] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - Self::new_uninit_slice_in(len, PanicAdapter(Global)) + Self::new_uninit_slice_in(len, AbortAlloc(Global)) } } @@ -522,7 +522,7 @@ impl Box { #[allow(clippy::inline_always)] #[inline(always)] pub unsafe fn from_raw(raw: *mut T) -> Self { - Self::from_raw_in(raw, PanicAdapter(Global)) + Self::from_raw_in(raw, AbortAlloc(Global)) } } diff --git a/src/raw_vec.rs b/src/raw_vec.rs index 7378798..4f271f7 100644 --- a/src/raw_vec.rs +++ b/src/raw_vec.rs @@ -6,7 +6,7 @@ use crate::{ DeallocRef, Global, NonZeroLayout, - PanicAdapter, + AbortAlloc, ReallocRef, }, boxed::Box, @@ -50,7 +50,7 @@ use core::{ /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. // Using `NonNull` + `PhantomData` instead of `Unique` to stay on stable as long as possible -pub struct RawVec> { +pub struct RawVec> { ptr: Unique, capacity: usize, build_alloc: A::BuildAlloc, @@ -88,7 +88,7 @@ impl RawVec { ptr: Unique::empty(), // FIXME(mark-i-m): use `cap` when ifs are allowed in const capacity: [0, !0][(mem::size_of::() == 0) as usize], - build_alloc: PanicAdapter(Global), + build_alloc: AbortAlloc(Global), } } @@ -109,7 +109,7 @@ impl RawVec { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, PanicAdapter(Global)) + Self::with_capacity_in(capacity, AbortAlloc(Global)) } /// Like `with_capacity`, but guarantees the buffer is zeroed. @@ -125,7 +125,7 @@ impl RawVec { #[inline] #[must_use] pub fn with_capacity_zeroed(capacity: usize) -> Self { - Self::with_capacity_zeroed_in(capacity, PanicAdapter(Global)) + Self::with_capacity_zeroed_in(capacity, AbortAlloc(Global)) } /// Reconstitutes a `RawVec` from a pointer, and capacity. @@ -137,7 +137,7 @@ impl RawVec { /// If the ptr and capacity come from a `RawVec` created with `Global`, then this is guaranteed. #[inline] pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { - Self::from_raw_parts_in(ptr, capacity, PanicAdapter(Global)) + Self::from_raw_parts_in(ptr, capacity, AbortAlloc(Global)) } } diff --git a/src/string.rs b/src/string.rs index 90836c3..16c3006 100644 --- a/src/string.rs +++ b/src/string.rs @@ -52,7 +52,7 @@ //! ``` use crate::{ - alloc::{AllocRef, DeallocRef, Global, PanicAdapter, ReallocRef}, + alloc::{AllocRef, DeallocRef, Global, AbortAlloc, ReallocRef}, boxed::Box, collections::CollectionAllocErr, iter::TryExtend, @@ -312,7 +312,7 @@ pub use liballoc::string::{ParseError, ToString}; /// [`Deref`]: ../../std/ops/trait.Deref.html /// [`as_str()`]: struct.String.html#method.as_str #[derive(PartialOrd, Eq, Ord)] -pub struct String> { +pub struct String> { vec: Vec, } @@ -354,7 +354,7 @@ pub struct String> { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[derive(Debug)] -pub struct FromUtf8Error> { +pub struct FromUtf8Error> { bytes: Vec, error: Utf8Error, } @@ -451,7 +451,7 @@ impl String { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, PanicAdapter(Global)) + Self::with_capacity_in(capacity, AbortAlloc(Global)) } /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] @@ -475,7 +475,7 @@ impl String { /// assert!(String::from_utf16(v).is_err()); /// ``` pub fn from_utf16(v: &[u16]) -> Result { - Self::from_utf16_in(v, PanicAdapter(Global)) + Self::from_utf16_in(v, AbortAlloc(Global)) } /// Decode a UTF-16 encoded slice `v` into a `String`, replacing @@ -560,7 +560,7 @@ impl String { /// ``` #[inline] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> Self { - Self::from_raw_parts_in(buf, length, capacity, PanicAdapter(Global)) + Self::from_raw_parts_in(buf, length, capacity, AbortAlloc(Global)) } } diff --git a/src/vec.rs b/src/vec.rs index 1096948..33f3f5e 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -69,7 +69,7 @@ //! [`vec!`]: ../macro.vec.html use crate::{ - alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, PanicAdapter, ReallocRef}, + alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, AbortAlloc, ReallocRef}, boxed::Box, clone::CloneIn, collections::CollectionAllocErr, @@ -328,7 +328,7 @@ use core::{ /// [`insert`]: Self::insert() /// [`reserve`]: Self::reserve /// [owned slice]: crate::boxed::Box -pub struct Vec> { +pub struct Vec> { buf: RawVec, len: usize, } @@ -401,7 +401,7 @@ impl Vec { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, PanicAdapter(Global)) + Self::with_capacity_in(capacity, AbortAlloc(Global)) } /// Creates a `Vec` directly from the raw components of another vector. @@ -664,7 +664,7 @@ impl Vec { /// # Examples /// /// ``` - /// use alloc_wg::{alloc::PanicAdapter, collections::CollectionAllocErr, vec::Vec}; + /// use alloc_wg::{alloc::AbortAlloc, collections::CollectionAllocErr, vec::Vec}; /// /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { /// let mut output = Vec::new(); @@ -2037,7 +2037,7 @@ impl Vec { #[doc(hidden)] pub fn from_elem(elem: T, n: usize) -> Vec { - from_elem_in(elem, n, PanicAdapter(Global)) + from_elem_in(elem, n, AbortAlloc(Global)) } #[doc(hidden)] @@ -2280,9 +2280,9 @@ impl FromIterator for Vec { #[inline] #[must_use] fn from_iter>(iter: I) -> Self { - >>::from_iter_in( + >>::from_iter_in( iter.into_iter(), - PanicAdapter(Global), + AbortAlloc(Global), ) } } @@ -2923,7 +2923,7 @@ impl From<&str> for Vec { /// /// [`Vec`]: struct.Vec.html /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html -pub struct IntoIter> { +pub struct IntoIter> { buf: RawVec, ptr: *const T, end: *const T, @@ -3069,7 +3069,7 @@ impl Drop for IntoIter { /// /// [`drain`]: struct.Vec.html#method.drain /// [`Vec`]: struct.Vec.html -pub struct Drain<'a, T, A: DeallocRef = PanicAdapter> { +pub struct Drain<'a, T, A: DeallocRef = AbortAlloc> { /// Index of tail to preserve tail_start: usize, /// Length of tail @@ -3162,7 +3162,7 @@ impl FusedIterator for Drain<'_, T, A> {} /// [`splice()`]: struct.Vec.html#method.splice /// [`Vec`]: struct.Vec.html #[derive(Debug)] -pub struct Splice<'a, I: Iterator + 'a, A = PanicAdapter> +pub struct Splice<'a, I: Iterator + 'a, A = AbortAlloc> where A: ReallocRef, // Because Drop can allocate { @@ -3284,7 +3284,7 @@ where /// An iterator produced by calling `drain_filter` on Vec. // #[derive(Debug)] -pub struct DrainFilter<'a, T, F, A: DeallocRef = PanicAdapter> +pub struct DrainFilter<'a, T, F, A: DeallocRef = AbortAlloc> where F: FnMut(&mut T) -> bool, { @@ -3347,7 +3347,7 @@ where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: DeallocRef = PanicAdapter> + struct BackshiftOnDrop<'a, 'b, T, F, A: DeallocRef = AbortAlloc> where F: FnMut(&mut T) -> bool, { From cd6d5bc604901d7244a60cf33ae8b76b3555f7a0 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 09:53:07 -0500 Subject: [PATCH 6/9] Use old module name --- src/alloc/{panic_adaptor.rs => abort.rs} | 0 src/alloc/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/alloc/{panic_adaptor.rs => abort.rs} (100%) diff --git a/src/alloc/panic_adaptor.rs b/src/alloc/abort.rs similarity index 100% rename from src/alloc/panic_adaptor.rs rename to src/alloc/abort.rs diff --git a/src/alloc/mod.rs b/src/alloc/mod.rs index 43e3c4f..58aae45 100644 --- a/src/alloc/mod.rs +++ b/src/alloc/mod.rs @@ -13,8 +13,8 @@ pub use liballoc::alloc::{handle_alloc_error, Layout}; #[cfg(feature = "std")] use std::alloc::System; -mod panic_adaptor; -pub use self::panic_adaptor::AbortAlloc; +mod abort; +pub use self::abort::AbortAlloc; /// Allocate memory with the global allocator. /// From 710ba7d1570655bd92d4b63d297b06e6c1f6170c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 09:49:55 -0500 Subject: [PATCH 7/9] Revert "Remove `AbortAlloc`" This reverts commit 708a298f1d1673cbc80e8697c06326e51c160563. --- src/alloc/abort.rs | 62 +++++++++++++++++++++++++++++++ src/alloc/mod.rs | 6 ++- src/boxed.rs | 77 +++++++++++++++++++++++++------------- src/clone.rs | 4 +- src/iter.rs | 2 +- src/raw_vec.rs | 25 ++++++------- src/string.rs | 76 ++++++++++++++++++++----------------- src/vec.rs | 93 ++++++++++++++++++++++++++-------------------- 8 files changed, 230 insertions(+), 115 deletions(-) create mode 100644 src/alloc/abort.rs diff --git a/src/alloc/abort.rs b/src/alloc/abort.rs new file mode 100644 index 0000000..723b610 --- /dev/null +++ b/src/alloc/abort.rs @@ -0,0 +1,62 @@ +#![allow(clippy::use_self)] + +use crate::alloc::{AllocRef, BuildAllocRef, DeallocRef, NonZeroLayout, ReallocRef}; +use core::ptr::NonNull; +use liballoc::alloc::handle_alloc_error; + +/// An allocator, which wraps another allocator and aborts on OOM. +#[derive(Debug, Default, Copy, Clone)] +pub struct AbortAlloc(pub A); + +impl BuildAllocRef for AbortAlloc { + type Ref = AbortAlloc; + + unsafe fn build_alloc_ref( + &mut self, + ptr: NonNull, + layout: Option, + ) -> Self::Ref { + Self(self.0.build_alloc_ref(ptr, layout)) + } +} + +impl DeallocRef for AbortAlloc { + type BuildAlloc = AbortAlloc; + + fn get_build_alloc(&mut self) -> Self::BuildAlloc { + Self(self.0.get_build_alloc()) + } + + unsafe fn dealloc(&mut self, ptr: NonNull, layout: NonZeroLayout) { + self.0.dealloc(ptr, layout) + } +} + +impl AllocRef for AbortAlloc { + type Error = !; + + fn alloc(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { + self.0 + .alloc(layout) + .map_err(|_| handle_alloc_error(layout.into())) + } + + fn alloc_zeroed(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { + self.0 + .alloc_zeroed(layout) + .map_err(|_| handle_alloc_error(layout.into())) + } +} + +impl ReallocRef for AbortAlloc { + unsafe fn realloc( + &mut self, + ptr: NonNull, + old_layout: NonZeroLayout, + new_layout: NonZeroLayout, + ) -> Result, Self::Error> { + self.0 + .realloc(ptr, old_layout, new_layout) + .map_err(|_| handle_alloc_error(new_layout.into())) + } +} diff --git a/src/alloc/mod.rs b/src/alloc/mod.rs index 0502890..5870301 100644 --- a/src/alloc/mod.rs +++ b/src/alloc/mod.rs @@ -1,6 +1,10 @@ +mod abort; mod layout; -pub use self::layout::{LayoutErr, NonZeroLayout}; +pub use self::{ + abort::AbortAlloc, + layout::{LayoutErr, NonZeroLayout}, +}; pub use core::alloc::GlobalAlloc; use core::{ cmp, diff --git a/src/boxed.rs b/src/boxed.rs index 074c91d..2b18624 100644 --- a/src/boxed.rs +++ b/src/boxed.rs @@ -79,7 +79,7 @@ //! [`NonZeroLayout::for_value(&*value)`]: crate::alloc::NonZeroLayout::for_value use crate::{ - alloc::{AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout}, + alloc::{AbortAlloc, AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout}, clone::CloneIn, collections::CollectionAllocErr, raw_vec::RawVec, @@ -105,7 +105,7 @@ use core::{ /// A pointer type for heap allocation. /// /// See the [module-level documentation](index.html) for more. -pub struct Box { +pub struct Box> { ptr: Unique, build_alloc: A::BuildAlloc, } @@ -131,7 +131,7 @@ impl Box { #[inline(always)] #[must_use] pub fn new(x: T) -> Self { - Self::new_in(x, Global) + Self::new_in(x, AbortAlloc(Global)) } /// Constructs a new box with uninitialized contents. @@ -156,7 +156,7 @@ impl Box { #[inline(always)] #[must_use] pub fn new_uninit() -> Box> { - Self::new_uninit_in(Global) + Self::new_uninit_in(AbortAlloc(Global)) } /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then @@ -177,14 +177,20 @@ impl Box { /// # Example /// /// ``` - /// use alloc_wg::{alloc::Global, boxed::Box}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// boxed::Box, + /// }; /// /// # #[allow(unused_variables)] - /// let five = Box::new_in(5, Global); + /// let five = Box::new_in(5, AbortAlloc(Global)); /// ``` #[allow(clippy::inline_always)] #[inline(always)] - pub fn new_in(x: T, a: A) -> Self { + pub fn new_in(x: T, a: A) -> Self + where + A: AllocRef, + { unsafe { Self::try_new_in(x, a).unwrap_unchecked() } } @@ -219,9 +225,12 @@ impl Box { /// # Example /// /// ``` - /// use alloc_wg::{alloc::Global, boxed::Box}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// boxed::Box, + /// }; /// - /// let mut five = Box::::new_uninit_in(Global); + /// let mut five = Box::::new_uninit_in(AbortAlloc(Global)); /// /// let five = unsafe { /// // Deferred initialization: @@ -234,7 +243,10 @@ impl Box { /// ``` #[allow(clippy::inline_always)] #[inline(always)] - pub fn new_uninit_in(a: A) -> Box, A> { + pub fn new_uninit_in(a: A) -> Box, A> + where + A: AllocRef, + { unsafe { Self::try_new_uninit_in(a).unwrap_unchecked() } } @@ -271,7 +283,10 @@ impl Box { /// `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 { + pub fn pin_in(x: T, a: A) -> Pin + where + A: AllocRef, + { unsafe { Self::try_pin_in(x, a).unwrap_unchecked() } } @@ -309,7 +324,7 @@ impl Box<[T]> { #[inline(always)] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - Self::new_uninit_slice_in(len, Global) + Self::new_uninit_slice_in(len, AbortAlloc(Global)) } } @@ -320,9 +335,12 @@ impl Box<[T], A> { /// # Example /// /// ``` - /// use alloc_wg::{alloc::Global, boxed::Box}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// boxed::Box, + /// }; /// - /// let mut values = Box::<[u32], _>::new_uninit_slice_in(3, Global); + /// let mut values = Box::<[u32], AbortAlloc>::new_uninit_slice_in(3, AbortAlloc(Global)); /// /// let values = unsafe { /// // Deferred initialization: @@ -337,7 +355,10 @@ impl Box<[T], A> { /// ``` #[allow(clippy::inline_always)] #[inline(always)] - pub fn new_uninit_slice_in(len: usize, a: A) -> Box<[mem::MaybeUninit], A> { + pub fn new_uninit_slice_in(len: usize, a: A) -> Box<[mem::MaybeUninit], A> + where + A: AllocRef, + { unsafe { Self::try_new_uninit_slice_in(len, a).unwrap_unchecked() } } @@ -503,7 +524,7 @@ impl Box { #[allow(clippy::inline_always)] #[inline(always)] pub unsafe fn from_raw(raw: *mut T) -> Self { - Self::from_raw_in(raw, Global) + Self::from_raw_in(raw, AbortAlloc(Global)) } } @@ -747,7 +768,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: DeallocRef> Drop for Box { impl Default for Box where T: Default, - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -758,7 +779,7 @@ where #[allow(clippy::use_self)] impl Default for Box<[T], A> where - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -775,7 +796,7 @@ unsafe fn from_boxed_utf8_unchecked(v: Box<[u8], A>) -> Box Default for Box where - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -785,7 +806,7 @@ where impl Clone for Box where - A: AllocRef, + A: AllocRef, A::BuildAlloc: Clone, { /// Returns a new box with a `clone()` of this box's contents. @@ -846,7 +867,10 @@ where impl CloneIn for Box { type Cloned = Box; - fn clone_in(&self, a: B) -> Self::Cloned { + fn clone_in(&self, a: B) -> Self::Cloned + where + B: AllocRef, + { Box::new_in(self.as_ref().clone(), a) } @@ -949,7 +973,7 @@ impl Hasher for Box { impl From for Box where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a generic type `T` into a `Box` /// @@ -983,7 +1007,7 @@ impl From> for Pin> { #[allow(clippy::use_self)] impl From<&[T]> for Box<[T], A> where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a `&[T]` into a `Box<[T], B>` /// @@ -1012,7 +1036,7 @@ where #[allow(clippy::use_self)] impl From<&str> for Box where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a `&str` into a `Box` /// @@ -1266,13 +1290,16 @@ macro_rules! impl_dispatch_from_dyn { } impl_dispatch_from_dyn!(Global); +impl_dispatch_from_dyn!(AbortAlloc); #[cfg(feature = "std")] impl_dispatch_from_dyn!(std::alloc::System); +#[cfg(feature = "std")] +impl_dispatch_from_dyn!(AbortAlloc); #[allow(clippy::items_after_statements)] impl Clone for Box<[T], A> where - A: AllocRef, + A: AllocRef, A::BuildAlloc: Clone, { fn clone(&self) -> Self { diff --git a/src/clone.rs b/src/clone.rs index 1fbe118..18b43d5 100644 --- a/src/clone.rs +++ b/src/clone.rs @@ -3,7 +3,9 @@ use crate::alloc::AllocRef; pub trait CloneIn: Sized { type Cloned; - fn clone_in(&self, a: A) -> Self::Cloned; + fn clone_in(&self, a: A) -> Self::Cloned + where + A: AllocRef; fn try_clone_in(&self, a: A) -> Result; } diff --git a/src/iter.rs b/src/iter.rs index 591701f..a6b5484 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -19,7 +19,7 @@ pub trait TryExtend { /// message.try_extend(['d', 'e', 'f'].iter())?; /// /// assert_eq!(vec!['a', 'b', 'c', 'd', 'e', 'f'], message); - /// # Ok::<(), alloc_wg::collections::CollectionAllocErr>(()) + /// # Ok::<(), alloc_wg::collections::CollectionAllocErr>>(()) /// ``` fn try_extend>(&mut self, iter: T) -> Result<(), Self::Err>; } diff --git a/src/raw_vec.rs b/src/raw_vec.rs index 3cc236c..dd53ead 100644 --- a/src/raw_vec.rs +++ b/src/raw_vec.rs @@ -1,6 +1,6 @@ use crate::{ alloc::{ - handle_alloc_error, + AbortAlloc, AllocRef, BuildAllocRef, CapacityOverflow, @@ -33,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 /// @@ -51,7 +50,7 @@ use core::{ /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. // Using `NonNull` + `PhantomData` instead of `Unique` to stay on stable as long as possible -pub struct RawVec { +pub struct RawVec> { ptr: Unique, capacity: usize, build_alloc: A::BuildAlloc, @@ -89,7 +88,7 @@ impl RawVec { ptr: Unique::empty(), // FIXME(mark-i-m): use `cap` when ifs are allowed in const capacity: [0, !0][(mem::size_of::() == 0) as usize], - build_alloc: Global, + build_alloc: AbortAlloc(Global), } } @@ -110,7 +109,7 @@ impl RawVec { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + Self::with_capacity_in(capacity, AbortAlloc(Global)) } /// Like `with_capacity`, but guarantees the buffer is zeroed. @@ -126,7 +125,7 @@ impl RawVec { #[inline] #[must_use] pub fn with_capacity_zeroed(capacity: usize) -> Self { - Self::with_capacity_zeroed_in(capacity, Global) + Self::with_capacity_zeroed_in(capacity, AbortAlloc(Global)) } /// Reconstitutes a `RawVec` from a pointer, and capacity. @@ -138,7 +137,7 @@ impl RawVec { /// If the ptr and capacity come from a `RawVec` created with `Global`, then this is guaranteed. #[inline] pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { - Self::from_raw_parts_in(ptr, capacity, Global) + Self::from_raw_parts_in(ptr, capacity, AbortAlloc(Global)) } } @@ -163,7 +162,7 @@ impl RawVec { /// * 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, { match Self::try_with_capacity_in(capacity, a) { Ok(vec) => vec, @@ -198,7 +197,7 @@ impl RawVec { /// * 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, { match Self::try_with_capacity_zeroed_in(capacity, a) { Ok(vec) => vec, @@ -418,7 +417,7 @@ impl RawVec { /// ``` pub fn double(&mut self) where - A: ReallocRef, + A: ReallocRef, { match self.try_double() { Ok(_) => (), @@ -588,7 +587,7 @@ impl RawVec { /// ``` pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { match self.try_reserve(used_capacity, needed_extra_capacity) { Ok(vec) => vec, @@ -631,7 +630,7 @@ impl RawVec { /// * on 32-bit platforms if the requested capacity exceeds `isize::MAX` bytes. pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { match self.try_reserve_exact(used_capacity, needed_extra_capacity) { Ok(_) => (), @@ -733,7 +732,7 @@ impl RawVec { /// Panics if the given amount is *larger* than the current capacity. pub fn shrink_to_fit(&mut self, amount: usize) where - A: ReallocRef, + A: ReallocRef, { match self.try_shrink_to_fit(amount) { Ok(_) => (), diff --git a/src/string.rs b/src/string.rs index 980f798..e9b1deb 100644 --- a/src/string.rs +++ b/src/string.rs @@ -52,7 +52,7 @@ //! ``` use crate::{ - alloc::{AllocRef, DeallocRef, Global, ReallocRef}, + alloc::{AbortAlloc, AllocRef, DeallocRef, Global, ReallocRef}, boxed::Box, collections::CollectionAllocErr, iter::TryExtend, @@ -312,7 +312,7 @@ pub use liballoc::string::{ParseError, ToString}; /// [`Deref`]: ../../std/ops/trait.Deref.html /// [`as_str()`]: struct.String.html#method.as_str #[derive(PartialOrd, Eq, Ord)] -pub struct String { +pub struct String> { vec: Vec, } @@ -354,7 +354,7 @@ pub struct String { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[derive(Debug)] -pub struct FromUtf8Error { +pub struct FromUtf8Error> { bytes: Vec, error: Utf8Error, } @@ -451,7 +451,7 @@ impl String { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + Self::with_capacity_in(capacity, AbortAlloc(Global)) } /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] @@ -475,7 +475,7 @@ impl String { /// assert!(String::from_utf16(v).is_err()); /// ``` pub fn from_utf16(v: &[u16]) -> Result { - Self::from_utf16_in(v, Global) + Self::from_utf16_in(v, AbortAlloc(Global)) } /// Decode a UTF-16 encoded slice `v` into a `String`, replacing @@ -560,7 +560,7 @@ impl String { /// ``` #[inline] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> Self { - Self::from_raw_parts_in(buf, length, capacity, Global) + Self::from_raw_parts_in(buf, length, capacity, AbortAlloc(Global)) } } @@ -580,7 +580,7 @@ impl String { #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self where - A: AllocRef, + A: AllocRef, { Self { vec: Vec::with_capacity_in(capacity, a), @@ -605,7 +605,7 @@ impl String { #[inline] pub fn from_str_in(s: &str, a: A) -> Self where - A: ReallocRef, + A: ReallocRef, { let mut v = Self::with_capacity_in(s.len(), a); v.push_str(s); @@ -705,7 +705,7 @@ impl String { /// Panics if allocation fails. pub fn from_utf8_lossy_in(v: &[u8], a: A) -> Self where - A: ReallocRef, + A: ReallocRef, { match Self::try_from_utf8_lossy_in(v, a) { Ok(s) => s, @@ -753,7 +753,7 @@ impl String { /// Like `from_utf16` but parameterized over the choice of allocator for the returned `String`. pub fn from_utf16_in(v: &[u16], a: A) -> Result where - A: ReallocRef, + A: ReallocRef, { // This isn't done via collect::>() for performance reasons. // FIXME: the function can be simplified again when #48994 is closed. @@ -928,7 +928,7 @@ impl String { #[inline] pub fn push_str(&mut self, string: &str) where - A: ReallocRef, + A: ReallocRef, { self.vec.extend_from_slice(string.as_bytes()) } @@ -1012,7 +1012,7 @@ impl String { #[inline] pub fn reserve(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.reserve(additional) } @@ -1065,7 +1065,7 @@ impl String { #[inline] pub fn reserve_exact(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.reserve_exact(additional) } @@ -1084,9 +1084,13 @@ impl String { /// # Examples /// /// ``` - /// use alloc_wg::{alloc::Global, collections::CollectionAllocErr, string::String}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// collections::CollectionAllocErr, + /// string::String, + /// }; /// - /// fn process_data(data: &str) -> Result> { + /// fn process_data(data: &str) -> Result>> { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -1123,9 +1127,13 @@ impl String { /// # Examples /// /// ``` - /// use alloc_wg::{alloc::Global, collections::CollectionAllocErr, string::String}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// collections::CollectionAllocErr, + /// string::String, + /// }; /// - /// fn process_data(data: &str) -> Result> { + /// fn process_data(data: &str) -> Result>> { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -1168,7 +1176,7 @@ impl String { #[inline] pub fn shrink_to_fit(&mut self) where - A: ReallocRef, + A: ReallocRef, { self.vec.shrink_to_fit() } @@ -1212,7 +1220,7 @@ impl String { #[inline] pub fn shrink_to(&mut self, min_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.shrink_to(min_capacity) } @@ -1251,7 +1259,7 @@ impl String { #[inline] pub fn push(&mut self, ch: char) where - A: ReallocRef, + A: ReallocRef, { match self.try_push(ch) { Ok(s) => s, @@ -1503,7 +1511,7 @@ impl String { #[inline] pub fn insert(&mut self, idx: usize, ch: char) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert(idx, ch) { Ok(s) => s, @@ -1578,7 +1586,7 @@ impl String { #[inline] pub fn insert_str(&mut self, idx: usize, string: &str) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert_str(idx, string) { Ok(s) => s, @@ -1591,7 +1599,7 @@ impl String { #[inline] pub fn try_insert_str(&mut self, idx: usize, string: &str) -> Result<(), CollectionAllocErr> where - A: ReallocRef, + A: ReallocRef, { assert!(self.is_char_boundary(idx)); @@ -1701,7 +1709,7 @@ impl String { #[inline] pub fn split_off(&mut self, at: usize) -> Self where - A: AllocRef, + A: AllocRef, { match self.try_split_off(at) { Ok(s) => s, @@ -1840,7 +1848,7 @@ impl String { pub fn replace_range(&mut self, range: R, replace_with: &str) where R: RangeBounds, - A: ReallocRef, + A: ReallocRef, { // Memory safety // @@ -1885,7 +1893,7 @@ impl String { #[inline] pub fn into_boxed_str(self) -> Box where - A: ReallocRef, + A: ReallocRef, { let slice = self.vec.into_boxed_slice(); unsafe { from_boxed_utf8_unchecked(slice) } @@ -2091,7 +2099,7 @@ impl<'a> FromIterator> for String { impl Extend for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { let iterator = iter.into_iter(); @@ -2115,7 +2123,7 @@ impl TryExtend for String { impl<'a, A> Extend<&'a char> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); @@ -2132,7 +2140,7 @@ impl<'a, A: ReallocRef> TryExtend<&'a char> for String { impl<'a, A> Extend<&'a str> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); @@ -2149,7 +2157,7 @@ impl<'a, A: ReallocRef> TryExtend<&'a str> for String { impl Extend> for String where - A: ReallocRef, + A: ReallocRef, B: DeallocRef, { fn extend>>(&mut self, iter: I) { @@ -2169,7 +2177,7 @@ impl TryExtend> for String { #[cfg(feature = "std")] impl<'a, A> Extend> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); @@ -2305,7 +2313,7 @@ impl hash::Hash for String { /// ``` impl Add<&str> for String where - A: ReallocRef, + A: ReallocRef, { type Output = Self; @@ -2321,7 +2329,7 @@ where /// This has the same behavior as the [`push_str`][`String::push_str`] method. impl AddAssign<&str> for String where - A: ReallocRef, + A: ReallocRef, { #[inline] fn add_assign(&mut self, other: &str) { @@ -2497,7 +2505,7 @@ impl From> for String { impl From> for Box where - A: ReallocRef, + A: ReallocRef, { /// Converts the given `String` to a boxed `str` slice that is owned. /// diff --git a/src/vec.rs b/src/vec.rs index 50b7b45..87847b0 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -69,7 +69,7 @@ //! [`vec!`]: ../macro.vec.html use crate::{ - alloc::{handle_alloc_error, AllocRef, BuildAllocRef, DeallocRef, Global, ReallocRef}, + alloc::{AbortAlloc, AllocRef, BuildAllocRef, DeallocRef, Global, ReallocRef}, boxed::Box, clone::CloneIn, collections::CollectionAllocErr, @@ -328,7 +328,7 @@ use core::{ /// [`insert`]: Self::insert() /// [`reserve`]: Self::reserve /// [owned slice]: crate::boxed::Box -pub struct Vec { +pub struct Vec> { buf: RawVec, len: usize, } @@ -401,7 +401,7 @@ impl Vec { #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + Self::with_capacity_in(capacity, AbortAlloc(Global)) } /// Creates a `Vec` directly from the raw components of another vector. @@ -490,7 +490,7 @@ impl Vec { #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self where - A: AllocRef, + A: AllocRef, { Self { buf: RawVec::with_capacity_in(capacity, a), @@ -612,7 +612,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn reserve(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.reserve(self.len, additional); } @@ -645,7 +645,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn reserve_exact(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.reserve_exact(self.len, additional); } @@ -664,9 +664,13 @@ impl Vec { /// # Examples /// /// ``` - /// use alloc_wg::{alloc::Global, collections::CollectionAllocErr, vec::Vec}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// collections::CollectionAllocErr, + /// vec::Vec, + /// }; /// - /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr>> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -705,9 +709,13 @@ impl Vec { /// # Examples /// /// ``` - /// use alloc_wg::{alloc::Global, collections::CollectionAllocErr, vec::Vec}; + /// use alloc_wg::{ + /// alloc::{AbortAlloc, Global}, + /// collections::CollectionAllocErr, + /// vec::Vec, + /// }; /// - /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr>> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -751,7 +759,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn shrink_to_fit(&mut self) where - A: ReallocRef, + A: ReallocRef, { if self.capacity() != self.len { self.buf.shrink_to_fit(self.len); @@ -797,7 +805,7 @@ impl Vec { /// * Panics if the reallocation fails. pub fn shrink_to(&mut self, min_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); } @@ -844,7 +852,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn into_boxed_slice(self) -> Box<[T], A> where - A: ReallocRef, + A: ReallocRef, { match self.try_into_boxed_slice() { Ok(vec) => vec, @@ -1188,7 +1196,7 @@ impl Vec { /// ``` pub fn insert(&mut self, index: usize, element: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert(index, element) { Ok(vec) => vec, @@ -1294,7 +1302,7 @@ impl Vec { pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, - A: ReallocRef, + A: ReallocRef, { self.drain_filter(|x| !f(x)); } @@ -1377,7 +1385,7 @@ impl Vec { #[inline] pub fn push(&mut self, value: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_push(value) { Ok(vec) => vec, @@ -1462,7 +1470,7 @@ impl Vec { #[inline] pub fn append(&mut self, other: &mut Self) where - A: ReallocRef, + A: ReallocRef, { match self.try_append(other) { Ok(vec) => vec, @@ -1647,7 +1655,7 @@ impl Vec { #[inline] pub fn split_off(&mut self, at: usize) -> Self where - A: AllocRef, + A: AllocRef, { match self.try_split_off(at) { Ok(vec) => vec, @@ -1717,7 +1725,7 @@ impl Vec { pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T, - A: ReallocRef, + A: ReallocRef, { match self.try_resize_with(new_len, f) { Ok(vec) => vec, @@ -1771,7 +1779,7 @@ impl Vec { pub fn leak<'a>(vec: Self) -> &'a mut [T] where T: 'a, // Technically not needed, but kept to be explicit. - A: ReallocRef, + A: ReallocRef, { Box::leak(vec.into_boxed_slice()) } @@ -1818,12 +1826,14 @@ impl Vec { /// # Panics /// /// Panics if the reallocation fails. - pub fn resize(&mut self, new_len: usize, value: T) { + pub fn resize(&mut self, new_len: usize, value: T) + where + A: ReallocRef, + { match self.try_resize(new_len, value) { Ok(_) => (), Err(CollectionAllocErr::CapacityOverflow) => capacity_overflow(), - Err(CollectionAllocErr::AllocError { layout, .. }) => handle_alloc_error(layout.into()), - } + Err(CollectionAllocErr::AllocError { layout, .. }) => handle_alloc_error(layout.into()) } } /// Same as `resize` but returns errors instead of panicking @@ -1862,8 +1872,11 @@ impl Vec { /// # Panics /// /// Panics if the reallocation fails. - pub fn extend_from_slice(&mut self, other: &[T]) { - self.spec_extend(other.iter()) + pub fn extend_from_slice(&mut self, other: &[T]) + where + A: ReallocRef, + { + self.extend(other.iter().cloned()) } /// Same as `extend_from_slice` but returns errors instead of panicking @@ -2030,7 +2043,7 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[doc(hidden)] pub fn from_elem_in(elem: T, n: usize, a: A) -> Vec where - A: ReallocRef, + A: ReallocRef, { match try_from_elem_in(elem, n, a) { Ok(vec) => vec, @@ -2349,7 +2362,7 @@ impl<'a, T, A: DeallocRef> IntoIterator for &'a mut Vec { impl Extend for Vec where - A: ReallocRef, + A: ReallocRef, { #[inline] fn extend>(&mut self, iter: I) { @@ -2590,7 +2603,7 @@ impl Vec { #[inline] pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> where - A: ReallocRef, + A: ReallocRef, R: RangeBounds, I: IntoIterator, { @@ -2649,7 +2662,7 @@ impl Vec { /// ``` pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> where - A: ReallocRef, + A: ReallocRef, F: FnMut(&mut T) -> bool, { let old_len = self.len(); @@ -2678,7 +2691,7 @@ impl Vec { /// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice impl<'a, T: 'a + Copy, A> Extend<&'a T> for Vec where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()) @@ -3042,7 +3055,7 @@ impl Drop for IntoIter { /// /// [`drain`]: struct.Vec.html#method.drain /// [`Vec`]: struct.Vec.html -pub struct Drain<'a, T, A: DeallocRef = Global> { +pub struct Drain<'a, T, A: DeallocRef = AbortAlloc> { /// Index of tail to preserve tail_start: usize, /// Length of tail @@ -3135,9 +3148,9 @@ impl FusedIterator for Drain<'_, T, A> {} /// [`splice()`]: struct.Vec.html#method.splice /// [`Vec`]: struct.Vec.html #[derive(Debug)] -pub struct Splice<'a, I: Iterator + 'a, A = Global> +pub struct Splice<'a, I: Iterator + 'a, A = AbortAlloc> where - A: ReallocRef, + A: ReallocRef, { drain: Drain<'a, I::Item, A>, replace_with: I, @@ -3145,7 +3158,7 @@ where impl Iterator for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { type Item = I::Item; @@ -3160,18 +3173,18 @@ where impl DoubleEndedIterator for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { fn next_back(&mut self) -> Option { self.drain.next_back() } } -impl ExactSizeIterator for Splice<'_, I, A> where A: ReallocRef {} +impl ExactSizeIterator for Splice<'_, I, A> where A: ReallocRef {} impl Drop for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { fn drop(&mut self) { self.drain.by_ref().for_each(drop); @@ -3217,7 +3230,7 @@ where /// Private helper methods for `Splice::drop` impl Drain<'_, T, A> where - A: ReallocRef, + A: ReallocRef, { /// The range from `self.vec.len` to `self.tail_start` contains elements /// that have been moved out. @@ -3257,7 +3270,7 @@ where /// An iterator produced by calling `drain_filter` on Vec. // #[derive(Debug)] -pub struct DrainFilter<'a, T, F, A: DeallocRef = Global> +pub struct DrainFilter<'a, T, F, A: DeallocRef = AbortAlloc> where F: FnMut(&mut T) -> bool, { @@ -3320,7 +3333,7 @@ where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: DeallocRef = Global> + struct BackshiftOnDrop<'a, 'b, T, F, A: DeallocRef = AbortAlloc> where F: FnMut(&mut T) -> bool, { From df1c75a2ca79d549a4f2b34999df861b104b1f58 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 09:55:19 -0500 Subject: [PATCH 8/9] Revert "Revert tests for `string` and `vec`" This reverts commit 0ab26631a097ae208928ae3b5e29276233f7f228. --- tests/string.rs | 23 ++++++++++++++++++----- tests/vec.rs | 17 +++++++++++------ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/string.rs b/tests/string.rs index d43ac4e..7fc5731 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -1,4 +1,11 @@ -use alloc_wg::{borrow::Cow, collections::CollectionAllocErr::*, string::String, vec, vec::Vec}; +use alloc_wg::{ + alloc::Global, + borrow::Cow, + collections::CollectionAllocErr::*, + string::String, + vec, + vec::Vec, +}; use core::{isize, mem::size_of, usize}; pub trait IntoCow<'a, B: ?Sized> @@ -576,7 +583,7 @@ fn test_try_reserve() { { // Note: basic stuff is checked by test_reserve - let mut empty_string = String::new(); + let mut empty_string = String::new_in(Global); // Check isize::MAX doesn't count as an overflow if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { @@ -616,7 +623,10 @@ fn test_try_reserve() { { // Same basic idea, but with non-zero len - let mut ten_bytes = String::from("0123456789"); + let mut ten_bytes = String::new_in(Global); + ten_bytes + .try_push_str("0123456789") + .expect("Could not create string with 10 bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -655,7 +665,7 @@ fn test_try_reserve_exact() { let guards_against_isize = size_of::() < 8; { - let mut empty_string = String::new(); + let mut empty_string = String::new_in(Global); if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -688,7 +698,10 @@ fn test_try_reserve_exact() { } { - let mut ten_bytes = String::from("0123456789"); + let mut ten_bytes = String::new_in(Global); + ten_bytes + .try_push_str("0123456789") + .expect("Could not create string with 10 bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); diff --git a/tests/vec.rs b/tests/vec.rs index 0cb43b6..ec4d189 100644 --- a/tests/vec.rs +++ b/tests/vec.rs @@ -1,4 +1,5 @@ use alloc_wg::{ + alloc::Global, boxed::Box, collections::CollectionAllocErr::*, vec, @@ -1125,7 +1126,7 @@ fn test_try_reserve() { { // Note: basic stuff is checked by test_reserve - let mut empty_bytes: Vec = Vec::new(); + let mut empty_bytes: Vec = Vec::new_in(Global); // Check isize::MAX doesn't count as an overflow if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { @@ -1163,7 +1164,8 @@ fn test_try_reserve() { { // Same basic idea, but with non-zero len - let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_bytes: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate ten bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1188,7 +1190,8 @@ fn test_try_reserve() { { // Same basic idea, but with interesting type size - let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_u32s: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate 40 bytes"); if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1225,7 +1228,7 @@ fn test_try_reserve_exact() { let guards_against_isize = size_of::() < 8; { - let mut empty_bytes: Vec = Vec::new(); + let mut empty_bytes: Vec = Vec::new_in(Global); if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1256,7 +1259,8 @@ fn test_try_reserve_exact() { } { - let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_bytes: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate ten bytes"); if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); @@ -1279,7 +1283,8 @@ fn test_try_reserve_exact() { } { - let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let mut ten_u32s: Vec = vec![try in Global; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + .expect("Unable to allocate 40 bytes"); if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); From c20cb95d2605076269b71eff0f13b7afb661ae65 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 30 Nov 2019 10:27:37 -0500 Subject: [PATCH 9/9] Use `Panic` for associated type rather than `!` for clarity --- src/alloc/abort.rs | 8 +++++- src/alloc/mod.rs | 2 +- src/boxed.rs | 36 +++++++++++++------------- src/clone.rs | 4 +-- src/iter.rs | 9 ++++--- src/raw_vec.rs | 13 +++++----- src/string.rs | 54 +++++++++++++++++++------------------- src/vec.rs | 64 +++++++++++++++++++++++----------------------- 8 files changed, 100 insertions(+), 90 deletions(-) diff --git a/src/alloc/abort.rs b/src/alloc/abort.rs index 21678d3..d7aed1b 100644 --- a/src/alloc/abort.rs +++ b/src/alloc/abort.rs @@ -24,6 +24,12 @@ use core::ptr::NonNull; #[derive(Copy, Clone, Debug, Default)] pub struct AbortAlloc(pub Alloc); +/// A synonym used to indicate the impossible case will be a panic instead. +/// +/// `!` in rust really does mean "never" / "impossible", but nothing in the type +/// system tracks panicking. +pub type Panic = !; + impl BuildAllocRef for AbortAlloc { type Ref = AbortAlloc; @@ -49,7 +55,7 @@ impl DeallocRef for AbortAlloc { } impl AllocRef for AbortAlloc { - type Error = !; + type Error = Panic; fn alloc(&mut self, layout: NonZeroLayout) -> Result, Self::Error> { self.0 diff --git a/src/alloc/mod.rs b/src/alloc/mod.rs index 5870301..5882151 100644 --- a/src/alloc/mod.rs +++ b/src/alloc/mod.rs @@ -2,7 +2,7 @@ mod abort; mod layout; pub use self::{ - abort::AbortAlloc, + abort::{AbortAlloc, Panic}, layout::{LayoutErr, NonZeroLayout}, }; pub use core::alloc::GlobalAlloc; diff --git a/src/boxed.rs b/src/boxed.rs index f2e9285..2a4ed93 100644 --- a/src/boxed.rs +++ b/src/boxed.rs @@ -79,7 +79,7 @@ //! [`NonZeroLayout::for_value(&*value)`]: crate::alloc::NonZeroLayout::for_value use crate::{ - alloc::{AbortAlloc, AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout}, + alloc::{AbortAlloc, AllocRef, BuildAllocRef, DeallocRef, Global, NonZeroLayout, Panic}, clone::CloneIn, collections::CollectionAllocErr, raw_vec::RawVec, @@ -188,7 +188,7 @@ impl Box { #[inline(always)] pub fn new_in(x: T, a: A) -> Self where - A: AllocRef, + A: AllocRef, { let Ok(b) = Self::try_new_in(x, a); b @@ -245,7 +245,7 @@ impl Box { #[inline(always)] pub fn new_uninit_in(a: A) -> Box, A> where - A: AllocRef, + A: AllocRef, { let Ok(b) = Self::try_new_uninit_in(a); b @@ -286,7 +286,7 @@ impl Box { #[inline(always)] pub fn pin_in(x: T, a: A) -> Pin where - A: AllocRef, + A: AllocRef, { let Ok(b) = Self::try_pin_in(x, a); b @@ -331,7 +331,7 @@ impl Box<[T]> { } #[allow(clippy::use_self)] -impl> Box<[T], A> { +impl> Box<[T], A> { /// Construct a new boxed slice with uninitialized contents with the spoecified allocator. /// /// # Example @@ -775,7 +775,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: DeallocRef> Drop for Box { impl Default for Box where T: Default, - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -784,9 +784,9 @@ where } #[allow(clippy::use_self)] -impl> Default for Box<[T], A> +impl> Default for Box<[T], A> where - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -801,9 +801,9 @@ unsafe fn from_boxed_utf8_unchecked(v: Box<[u8], A>) -> Box> Default for Box +impl> Default for Box where - A: Default + AllocRef, + A: Default + AllocRef, { #[must_use] fn default() -> Self { @@ -811,9 +811,9 @@ where } } -impl> Clone for Box +impl> Clone for Box where - A: AllocRef, + A: AllocRef, A::BuildAlloc: Clone, { /// Returns a new box with a `clone()` of this box's contents. @@ -876,7 +876,7 @@ impl CloneIn for Box { fn clone_in(&self, a: B) -> Self::Cloned where - B: AllocRef, + B: AllocRef, { Box::new_in(self.as_ref().clone(), a) } @@ -978,9 +978,9 @@ impl Hasher for Box { } } -impl> From for Box +impl> From for Box where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a generic type `T` into a `Box` /// @@ -1014,7 +1014,7 @@ impl From> for Pin> { #[allow(clippy::use_self)] impl From<&[T]> for Box<[T], A> where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a `&[T]` into a `Box<[T], B>` /// @@ -1043,7 +1043,7 @@ where #[allow(clippy::use_self)] impl From<&str> for Box where - A: Default + AllocRef, + A: Default + AllocRef, { /// Converts a `&str` into a `Box` /// @@ -1306,7 +1306,7 @@ impl_dispatch_from_dyn!(AbortAlloc); #[allow(clippy::items_after_statements)] impl Clone for Box<[T], A> where - A: AllocRef, + A: AllocRef, A::BuildAlloc: Clone, { fn clone(&self) -> Self { diff --git a/src/clone.rs b/src/clone.rs index 18b43d5..ee4a970 100644 --- a/src/clone.rs +++ b/src/clone.rs @@ -1,11 +1,11 @@ -use crate::alloc::AllocRef; +use crate::alloc::{AllocRef, Panic}; pub trait CloneIn: Sized { type Cloned; fn clone_in(&self, a: A) -> Self::Cloned where - A: AllocRef; + A: AllocRef; fn try_clone_in(&self, a: A) -> Result; } diff --git a/src/iter.rs b/src/iter.rs index d511f34..4e44bc1 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,4 +1,7 @@ -use crate::{alloc::AllocRef, collections::CollectionAllocErr}; +use crate::{ + alloc::{AllocRef, Panic}, + collections::CollectionAllocErr, +}; /// Extend a collection "fallibly" with the contents of an iterator. pub trait TryExtend { @@ -27,7 +30,7 @@ pub trait TryExtend { pub trait FromIteratorIn { fn from_iter_in>(iter: I, allocator: A) -> Self where - A: AllocRef; + A: AllocRef; fn try_from_iter_in>( iter: I, @@ -42,7 +45,7 @@ pub trait IteratorExt: Iterator + Sized { #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect_in, A: AllocRef>(self, allocator: A) -> T where - A: AllocRef, + A: AllocRef, { FromIteratorIn::from_iter_in(self, allocator) } diff --git a/src/raw_vec.rs b/src/raw_vec.rs index 1f41254..4cbd037 100644 --- a/src/raw_vec.rs +++ b/src/raw_vec.rs @@ -7,6 +7,7 @@ use crate::{ DeallocRef, Global, NonZeroLayout, + Panic, ReallocRef, }, boxed::Box, @@ -162,7 +163,7 @@ impl RawVec { /// * 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, { match Self::try_with_capacity_in(capacity, a) { Ok(vec) => vec, @@ -198,7 +199,7 @@ impl RawVec { /// * 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, { match Self::try_with_capacity_zeroed_in(capacity, a) { Ok(vec) => vec, @@ -419,7 +420,7 @@ impl RawVec { /// ``` pub fn double(&mut self) where - A: ReallocRef, + A: ReallocRef, { match self.try_double() { Ok(_) => (), @@ -590,7 +591,7 @@ impl RawVec { /// ``` pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { match self.try_reserve(used_capacity, needed_extra_capacity) { Ok(vec) => vec, @@ -634,7 +635,7 @@ impl RawVec { /// * on 32-bit platforms if the requested capacity exceeds `isize::MAX` bytes. pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { match self.try_reserve_exact(used_capacity, needed_extra_capacity) { Ok(_) => (), @@ -736,7 +737,7 @@ impl RawVec { /// Panics if the given amount is *larger* than the current capacity. pub fn shrink_to_fit(&mut self, amount: usize) where - A: ReallocRef, + A: ReallocRef, { match self.try_shrink_to_fit(amount) { Ok(_) => (), diff --git a/src/string.rs b/src/string.rs index 71e01a4..e2001fc 100644 --- a/src/string.rs +++ b/src/string.rs @@ -52,7 +52,7 @@ //! ``` use crate::{ - alloc::{AbortAlloc, AllocRef, DeallocRef, Global, ReallocRef}, + alloc::{AbortAlloc, AllocRef, DeallocRef, Global, Panic, ReallocRef}, boxed::Box, collections::CollectionAllocErr, iter::TryExtend, @@ -580,7 +580,7 @@ impl String { #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self where - A: AllocRef, + A: AllocRef, { match Self::try_with_capacity_in(capacity, a) { Ok(vec) => vec, @@ -608,7 +608,7 @@ impl String { #[inline] pub fn from_str_in(s: &str, a: A) -> Self where - A: ReallocRef, + A: ReallocRef, { let mut v = Self::with_capacity_in(s.len(), a); v.push_str(s); @@ -708,7 +708,7 @@ impl String { /// Panics if allocation fails. pub fn from_utf8_lossy_in(v: &[u8], a: A) -> Self where - A: ReallocRef, + A: ReallocRef, { match Self::try_from_utf8_lossy_in(v, a) { Ok(s) => s, @@ -757,7 +757,7 @@ impl String { /// Like `from_utf16` but parameterized over the choice of allocator for the returned `String`. pub fn from_utf16_in(v: &[u16], a: A) -> Result where - A: ReallocRef, + A: ReallocRef, { // This isn't done via collect::>() for performance reasons. // FIXME: the function can be simplified again when #48994 is closed. @@ -932,7 +932,7 @@ impl String { #[inline] pub fn push_str(&mut self, string: &str) where - A: ReallocRef, + A: ReallocRef, { self.vec.extend_from_slice(string.as_bytes()) } @@ -1016,7 +1016,7 @@ impl String { #[inline] pub fn reserve(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.reserve(additional) } @@ -1069,7 +1069,7 @@ impl String { #[inline] pub fn reserve_exact(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.reserve_exact(additional) } @@ -1180,7 +1180,7 @@ impl String { #[inline] pub fn shrink_to_fit(&mut self) where - A: ReallocRef, + A: ReallocRef, { self.vec.shrink_to_fit() } @@ -1224,7 +1224,7 @@ impl String { #[inline] pub fn shrink_to(&mut self, min_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { self.vec.shrink_to(min_capacity) } @@ -1263,7 +1263,7 @@ impl String { #[inline] pub fn push(&mut self, ch: char) where - A: ReallocRef, + A: ReallocRef, { match self.try_push(ch) { Ok(s) => s, @@ -1516,7 +1516,7 @@ impl String { #[inline] pub fn insert(&mut self, idx: usize, ch: char) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert(idx, ch) { Ok(s) => s, @@ -1592,7 +1592,7 @@ impl String { #[inline] pub fn insert_str(&mut self, idx: usize, string: &str) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert_str(idx, string) { Ok(s) => s, @@ -1606,7 +1606,7 @@ impl String { #[inline] pub fn try_insert_str(&mut self, idx: usize, string: &str) -> Result<(), CollectionAllocErr> where - A: ReallocRef, + A: ReallocRef, { assert!(self.is_char_boundary(idx)); @@ -1716,7 +1716,7 @@ impl String { #[inline] pub fn split_off(&mut self, at: usize) -> Self where - A: AllocRef, + A: AllocRef, { match self.try_split_off(at) { Ok(s) => s, @@ -1856,7 +1856,7 @@ impl String { pub fn replace_range(&mut self, range: R, replace_with: &str) where R: RangeBounds, - A: ReallocRef, + A: ReallocRef, { // Memory safety // @@ -1901,7 +1901,7 @@ impl String { #[inline] pub fn into_boxed_str(self) -> Box where - A: ReallocRef, + A: ReallocRef, { let slice = self.vec.into_boxed_slice(); unsafe { from_boxed_utf8_unchecked(slice) } @@ -2007,7 +2007,7 @@ impl fmt::Display for FromUtf16Error { } } -impl> Clone for String +impl> Clone for String where A: AllocRef, A::BuildAlloc: Clone, @@ -2033,7 +2033,7 @@ impl CloneIn for String { #[must_use = "Cloning is expected to be expensive"] fn clone_in(&self, a: B) -> Self::Cloned where - B: AllocRef, + B: AllocRef, { String { vec: self.vec.clone_in(a), @@ -2110,7 +2110,7 @@ impl<'a> FromIterator> for String { impl Extend for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { let iterator = iter.into_iter(); @@ -2134,7 +2134,7 @@ impl TryExtend for String { impl<'a, A> Extend<&'a char> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); @@ -2151,7 +2151,7 @@ impl<'a, A: ReallocRef> TryExtend<&'a char> for String { impl<'a, A> Extend<&'a str> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); @@ -2168,7 +2168,7 @@ impl<'a, A: ReallocRef> TryExtend<&'a str> for String { impl Extend> for String where - A: ReallocRef, + A: ReallocRef, B: DeallocRef, { fn extend>>(&mut self, iter: I) { @@ -2188,7 +2188,7 @@ impl TryExtend> for String { #[cfg(feature = "std")] impl<'a, A> Extend> for String where - A: ReallocRef, + A: ReallocRef, { fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); @@ -2324,7 +2324,7 @@ impl hash::Hash for String { /// ``` impl Add<&str> for String where - A: ReallocRef, + A: ReallocRef, { type Output = Self; @@ -2340,7 +2340,7 @@ where /// This has the same behavior as the [`push_str`][`String::push_str`] method. impl AddAssign<&str> for String where - A: ReallocRef, + A: ReallocRef, { #[inline] fn add_assign(&mut self, other: &str) { @@ -2516,7 +2516,7 @@ impl From> for String { impl From> for Box where - A: ReallocRef, + A: ReallocRef, { /// Converts the given `String` to a boxed `str` slice that is owned. /// diff --git a/src/vec.rs b/src/vec.rs index 0e35199..e8e262b 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -69,7 +69,7 @@ //! [`vec!`]: ../macro.vec.html use crate::{ - alloc::{AbortAlloc, AllocRef, BuildAllocRef, DeallocRef, Global, ReallocRef}, + alloc::{AbortAlloc, AllocRef, BuildAllocRef, DeallocRef, Global, Panic, ReallocRef}, boxed::Box, clone::CloneIn, collections::CollectionAllocErr, @@ -490,7 +490,7 @@ impl Vec { #[inline] pub fn with_capacity_in(capacity: usize, a: A) -> Self where - A: AllocRef, + A: AllocRef, { Self { buf: RawVec::with_capacity_in(capacity, a), @@ -612,7 +612,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn reserve(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.reserve(self.len, additional); } @@ -645,7 +645,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn reserve_exact(&mut self, additional: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.reserve_exact(self.len, additional); } @@ -759,7 +759,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn shrink_to_fit(&mut self) where - A: ReallocRef, + A: ReallocRef, { if self.capacity() != self.len { self.buf.shrink_to_fit(self.len); @@ -805,7 +805,7 @@ impl Vec { /// * Panics if the reallocation fails. pub fn shrink_to(&mut self, min_capacity: usize) where - A: ReallocRef, + A: ReallocRef, { self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); } @@ -852,7 +852,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn into_boxed_slice(self) -> Box<[T], A> where - A: ReallocRef, + A: ReallocRef, { match self.try_into_boxed_slice() { Ok(vec) => vec, @@ -1197,7 +1197,7 @@ impl Vec { /// ``` pub fn insert(&mut self, index: usize, element: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_insert(index, element) { Ok(vec) => vec, @@ -1304,7 +1304,7 @@ impl Vec { pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, - A: ReallocRef, + A: ReallocRef, { self.drain_filter(|x| !f(x)); } @@ -1387,7 +1387,7 @@ impl Vec { #[inline] pub fn push(&mut self, value: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_push(value) { Ok(vec) => vec, @@ -1473,7 +1473,7 @@ impl Vec { #[inline] pub fn append(&mut self, other: &mut Self) where - A: ReallocRef, + A: ReallocRef, { match self.try_append(other) { Ok(vec) => vec, @@ -1659,7 +1659,7 @@ impl Vec { #[inline] pub fn split_off(&mut self, at: usize) -> Self where - A: AllocRef, + A: AllocRef, { match self.try_split_off(at) { Ok(vec) => vec, @@ -1730,7 +1730,7 @@ impl Vec { pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T, - A: ReallocRef, + A: ReallocRef, { match self.try_resize_with(new_len, f) { Ok(vec) => vec, @@ -1785,7 +1785,7 @@ impl Vec { pub fn leak<'a>(vec: Self) -> &'a mut [T] where T: 'a, // Technically not needed, but kept to be explicit. - A: ReallocRef, + A: ReallocRef, { Box::leak(vec.into_boxed_slice()) } @@ -1834,7 +1834,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn resize(&mut self, new_len: usize, value: T) where - A: ReallocRef, + A: ReallocRef, { match self.try_resize(new_len, value) { Ok(_) => (), @@ -1882,7 +1882,7 @@ impl Vec { /// Panics if the reallocation fails. pub fn extend_from_slice(&mut self, other: &[T]) where - A: ReallocRef, + A: ReallocRef, { self.spec_extend(other.iter().cloned()) } @@ -2051,7 +2051,7 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[doc(hidden)] pub fn from_elem_in(elem: T, n: usize, a: A) -> Vec where - A: ReallocRef, + A: ReallocRef, { match try_from_elem_in(elem, n, a) { Ok(vec) => vec, @@ -2199,7 +2199,7 @@ unsafe impl IsZero for Option> { // Common trait implementations for Vec //////////////////////////////////////////////////////////////////////////////// -impl> Clone for Vec +impl> Clone for Vec where A: AllocRef, A::BuildAlloc: Clone, @@ -2224,7 +2224,7 @@ impl CloneIn for Vec { fn clone_in(&self, a: B) -> Self::Cloned where - B: AllocRef, + B: AllocRef, { let Ok(v) = self.try_clone_in(a); v @@ -2300,7 +2300,7 @@ impl FromIteratorIn for Vec { #[must_use] fn from_iter_in>(iter: I, a: A) -> Self where - A: AllocRef, + A: AllocRef, { >::from_iter_in(iter.into_iter(), a) } @@ -2376,7 +2376,7 @@ impl<'a, T, A: DeallocRef> IntoIterator for &'a mut Vec { impl Extend for Vec where - A: ReallocRef, + A: ReallocRef, { #[inline] fn extend>(&mut self, iter: I) { @@ -2397,7 +2397,7 @@ trait SpecExtend: Sized { #[inline] fn from_iter_in(iter: I, a: A) -> Self where - A: AllocRef, + A: AllocRef, { match Self::try_from_iter_in(iter, a) { Ok(v) => v, @@ -2412,7 +2412,7 @@ trait SpecExtend: Sized { #[inline] fn spec_extend(&mut self, iter: I) where - A: AllocRef, + A: AllocRef, { match self.try_spec_extend(iter) { Ok(_) => (), @@ -2625,7 +2625,7 @@ impl Vec { #[inline] pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> where - A: ReallocRef, + A: ReallocRef, R: RangeBounds, I: IntoIterator, { @@ -2684,7 +2684,7 @@ impl Vec { /// ``` pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> where - A: ReallocRef, + A: ReallocRef, F: FnMut(&mut T) -> bool, { let old_len = self.len(); @@ -2713,7 +2713,7 @@ impl Vec { /// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice impl<'a, T: 'a + Copy, A> Extend<&'a T> for Vec where - A: ReallocRef, + A: ReallocRef, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()) @@ -3172,7 +3172,7 @@ impl FusedIterator for Drain<'_, T, A> {} #[derive(Debug)] pub struct Splice<'a, I: Iterator + 'a, A = AbortAlloc> where - A: ReallocRef, // Because Drop can allocate + A: ReallocRef, // Because Drop can allocate { drain: Drain<'a, I::Item, A>, replace_with: I, @@ -3180,7 +3180,7 @@ where impl Iterator for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { type Item = I::Item; @@ -3195,18 +3195,18 @@ where impl DoubleEndedIterator for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { fn next_back(&mut self) -> Option { self.drain.next_back() } } -impl ExactSizeIterator for Splice<'_, I, A> where A: ReallocRef {} +impl ExactSizeIterator for Splice<'_, I, A> where A: ReallocRef {} impl Drop for Splice<'_, I, A> where - A: ReallocRef, + A: ReallocRef, { fn drop(&mut self) { self.drain.by_ref().for_each(drop); @@ -3252,7 +3252,7 @@ where /// Private helper methods for `Splice::drop` impl Drain<'_, T, A> where - A: ReallocRef, + A: ReallocRef, { /// The range from `self.vec.len` to `self.tail_start` contains elements /// that have been moved out.