diff options
| author | bors <bors@rust-lang.org> | 2021-08-07 01:26:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-08-07 01:26:15 +0000 |
| commit | 996ff2e0a0f911f52bb1de6bdd0cfd5704de1fc9 (patch) | |
| tree | f10bdc2b1742f123ce140d43cb11d8f07dabfe92 /library/alloc/src | |
| parent | db3cb435c1197ef3e3919c03b7f81ca8bffbd007 (diff) | |
| parent | a294aa8d3d7b73b7de60c629ae202194cffeb2f4 (diff) | |
| download | rust-996ff2e0a0f911f52bb1de6bdd0cfd5704de1fc9.tar.gz rust-996ff2e0a0f911f52bb1de6bdd0cfd5704de1fc9.zip | |
Auto merge of #87408 - kornelski:try_reserve_error, r=yaahc
Hide allocator details from TryReserveError I think there's [no need for TryReserveError to carry detailed information](https://github.com/rust-lang/rust/issues/48043#issuecomment-825139280), but I wouldn't want that issue to delay stabilization of the `try_reserve` feature. So I'm proposing to stabilize `try_reserve` with a `TryReserveError` as an opaque structure, and if needed, expose error details later. This PR moves the `enum` to an unstable inner `TryReserveErrorKind` that lives under a separate feature flag. `TryReserveErrorKind` could possibly be left as an implementation detail forever, and the `TryReserveError` get methods such as `allocation_size() -> Option<usize>` or `layout() -> Option<Layout>` instead, or the details could be dropped completely to make try-reserve errors just a unit struct, and thus smaller and cheaper.
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/collections/mod.rs | 49 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/mod.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/raw_vec.rs | 20 |
3 files changed, 55 insertions, 17 deletions
diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 97bfe2f3984..3ee857f3399 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -58,7 +58,31 @@ use core::fmt::Display; /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] -pub enum TryReserveError { +pub struct TryReserveError { + kind: TryReserveErrorKind, +} + +impl TryReserveError { + /// Details about the allocation that caused the error + #[inline] + #[unstable( + feature = "try_reserve_kind", + reason = "Uncertain how much info should be exposed", + issue = "48043" + )] + pub fn kind(&self) -> TryReserveErrorKind { + self.kind.clone() + } +} + +/// Details of the allocation that caused a `TryReserveError` +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable( + feature = "try_reserve_kind", + reason = "Uncertain how much info should be exposed", + issue = "48043" +)] +pub enum TryReserveErrorKind { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). CapacityOverflow, @@ -81,12 +105,23 @@ pub enum TryReserveError { }, } +#[unstable( + feature = "try_reserve_kind", + reason = "Uncertain how much info should be exposed", + issue = "48043" +)] +impl From<TryReserveErrorKind> for TryReserveError { + fn from(kind: TryReserveErrorKind) -> Self { + Self { kind } + } +} + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] impl From<LayoutError> for TryReserveError { - /// Always evaluates to [`TryReserveError::CapacityOverflow`]. + /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`]. #[inline] fn from(_: LayoutError) -> Self { - TryReserveError::CapacityOverflow + TryReserveErrorKind::CapacityOverflow.into() } } @@ -97,11 +132,13 @@ impl Display for TryReserveError { fmt: &mut core::fmt::Formatter<'_>, ) -> core::result::Result<(), core::fmt::Error> { fmt.write_str("memory allocation failed")?; - let reason = match &self { - TryReserveError::CapacityOverflow => { + let reason = match self.kind { + TryReserveErrorKind::CapacityOverflow => { " because the computed capacity exceeded the collection's maximum" } - TryReserveError::AllocError { .. } => " because the memory allocator returned a error", + TryReserveErrorKind::AllocError { .. } => { + " because the memory allocator returned a error" + } }; fmt.write_str(reason) } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 6bbddeb69b2..bea5cf11be5 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -19,6 +19,7 @@ use core::slice; use crate::alloc::{Allocator, Global}; use crate::collections::TryReserveError; +use crate::collections::TryReserveErrorKind; use crate::raw_vec::RawVec; use crate::vec::Vec; @@ -773,7 +774,7 @@ impl<T, A: Allocator> VecDeque<T, A> { let new_cap = used_cap .checked_add(additional) .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) - .ok_or(TryReserveError::CapacityOverflow)?; + .ok_or(TryReserveErrorKind::CapacityOverflow)?; if new_cap > old_cap { self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index d11d4031f77..3caada06f6b 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -13,7 +13,8 @@ use core::slice; use crate::alloc::handle_alloc_error; use crate::alloc::{Allocator, Global, Layout}; use crate::boxed::Box; -use crate::collections::TryReserveError::{self, *}; +use crate::collections::TryReserveError; +use crate::collections::TryReserveErrorKind::*; #[cfg(test)] mod tests; @@ -425,7 +426,7 @@ impl<T, A: Allocator> RawVec<T, A> { if mem::size_of::<T>() == 0 { // Since we return a capacity of `usize::MAX` when `elem_size` is // 0, getting to here necessarily means the `RawVec` is overfull. - return Err(CapacityOverflow); + return Err(CapacityOverflow.into()); } // Nothing we can really do about these checks, sadly. @@ -451,7 +452,7 @@ impl<T, A: Allocator> RawVec<T, A> { if mem::size_of::<T>() == 0 { // Since we return a capacity of `usize::MAX` when the type size is // 0, getting to here necessarily means the `RawVec` is overfull. - return Err(CapacityOverflow); + return Err(CapacityOverflow.into()); } let cap = len.checked_add(additional).ok_or(CapacityOverflow)?; @@ -471,10 +472,9 @@ impl<T, A: Allocator> RawVec<T, A> { let ptr = unsafe { let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - self.alloc.shrink(ptr, layout, new_layout).map_err(|_| TryReserveError::AllocError { - layout: new_layout, - non_exhaustive: (), - })? + self.alloc + .shrink(ptr, layout, new_layout) + .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? }; self.set_ptr(ptr); Ok(()) @@ -510,7 +510,7 @@ where alloc.allocate(new_layout) }; - memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }) + memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }.into()) } unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> { @@ -526,7 +526,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> { #[cfg(not(no_global_oom_handling))] #[inline] fn handle_reserve(result: Result<(), TryReserveError>) { - match result { + match result.map_err(|e| e.kind()) { Err(CapacityOverflow) => capacity_overflow(), Err(AllocError { layout, .. }) => handle_alloc_error(layout), Ok(()) => { /* yay */ } @@ -545,7 +545,7 @@ fn handle_reserve(result: Result<(), TryReserveError>) { #[inline] fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { if usize::BITS < 64 && alloc_size > isize::MAX as usize { - Err(CapacityOverflow) + Err(CapacityOverflow.into()) } else { Ok(()) } |
