diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-16 18:22:21 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-16 18:22:21 +0200 |
| commit | aec047edebb596c79852fc78c5cfcddbae595c08 (patch) | |
| tree | 4b956b14e1b92d0ccacbca8b2a78fab3e429c45c /src/liballoc/raw_vec.rs | |
| parent | e632dafba2782ce8f51c2e414290d36cf983896f (diff) | |
| parent | 59a340963fa5d8b5507d95cd015f7ca2855ba151 (diff) | |
| download | rust-aec047edebb596c79852fc78c5cfcddbae595c08.tar.gz rust-aec047edebb596c79852fc78c5cfcddbae595c08.zip | |
Rollup merge of #61780 - SimonSapin:container-error, r=Amanieu
Finalize the error type for `try_reserve`
See tracking issue comments from https://github.com/rust-lang/rust/issues/48043#issuecomment-500828346.
It is now:
```rust
/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub enum TryReserveError {
/// Error due to the computed capacity exceeding the collection's maximum
/// (usually `isize::MAX` bytes).
CapacityOverflow,
/// The memory allocator returned an error
AllocError {
/// The layout of allocation request that failed
layout: Layout,
#[doc(hidden)]
#[unstable(feature = "container_error_extra", issue = "0", reason = "\
Enable exposing the allocator’s custom error value \
if an associated type is added in the future: \
https://github.com/rust-lang/wg-allocators/issues/23")]
non_exhaustive: (),
},
}
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
impl From<LayoutErr> for TryReserveError {
#[inline]
fn from(_: LayoutErr) -> Self {
TryReserveError::CapacityOverflow
}
}
```
Changes:
* A `Layout` is included. Firefox wants to log the size of failed allocations. If this were not part of the return value of e.g. `HashMap::try_reserve`, users would only be able to estimate based on `HashMap::capacity` and assumptions about the allocation strategy of `HashMap`.
* There’s a dummy field that can stay unstable when `try_reserve` and the rest of this enum are stabilized. This forces non-exhaustive matching ~(https://github.com/rust-lang/rust/issues/44109 is not implemented yet for variants)~ and allows adding another field in the future if we want to expose custom error values from the allocator. See https://github.com/rust-lang/wg-allocators/issues/23.
- If the `Alloc` trait is stabilized without an associated error type and with a zero-size `AllocErr` type, we can simply remove this dummy field.
- If an associated type is added, we can add a default type parameter to `ContainerError` and a generic field to the `AllocError` variant.
* ~Moved from the `collections` module to the `alloc` module, and replaced `Collection` in the enum name with `Container`. The wold collection implies a multiplicity of items which is not relevant to this type. For example we may want to use this error type in a future `Box::try_new` method.~
- Renamed to `TryReserveError`, after the methods that involve this type: https://github.com/rust-lang/rust/pull/61780#issuecomment-501392487
* Replaced `Err` with `Error` in the enum and variant names. There is more precedent for this in https://doc.rust-lang.org/std/error/trait.Error.html#implementors, `AllocErr` and `LayoutErr` are the odd ones.
* ~Dropped `Alloc` in the enum name. `ContainerAllocError` with a mouthful, and being in the `alloc` module already provides the same indication.~
Diffstat (limited to 'src/liballoc/raw_vec.rs')
| -rw-r--r-- | src/liballoc/raw_vec.rs | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 0abab45e920..bc8a38f6b3a 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -7,8 +7,8 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{Alloc, Layout, Global, handle_alloc_error}; -use crate::collections::CollectionAllocErr::{self, *}; +use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error}; +use crate::collections::TryReserveError::{self, *}; use crate::boxed::Box; #[cfg(test)] @@ -385,7 +385,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<(), CollectionAllocErr> { + -> Result<(), TryReserveError> { self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact) } @@ -413,7 +413,7 @@ impl<T, A: Alloc> RawVec<T, A> { pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) { match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } @@ -422,7 +422,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// needed_extra_capacity` elements. This logic is used in amortized reserve methods. /// Returns `(new_capacity, new_alloc_size)`. fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<usize, CollectionAllocErr> { + -> Result<usize, TryReserveError> { // Nothing we can really do about these checks :( let required_cap = used_capacity.checked_add(needed_extra_capacity) @@ -435,7 +435,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<(), CollectionAllocErr> { + -> Result<(), TryReserveError> { self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized) } @@ -494,7 +494,7 @@ impl<T, A: Alloc> RawVec<T, A> { pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) { match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } @@ -640,10 +640,8 @@ impl<T, A: Alloc> RawVec<T, A> { needed_extra_capacity: usize, fallibility: Fallibility, strategy: ReserveStrategy, - ) -> Result<(), CollectionAllocErr> { + ) -> Result<(), TryReserveError> { unsafe { - use crate::alloc::AllocErr; - // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to @@ -672,12 +670,16 @@ impl<T, A: Alloc> RawVec<T, A> { None => self.a.alloc(new_layout), }; - match (&res, fallibility) { + let ptr = match (res, fallibility) { (Err(AllocErr), Infallible) => handle_alloc_error(new_layout), - _ => {} - } + (Err(AllocErr), Fallible) => return Err(TryReserveError::AllocError { + layout: new_layout, + non_exhaustive: (), + }), + (Ok(ptr), _) => ptr, + }; - self.ptr = res?.cast().into(); + self.ptr = ptr.cast().into(); self.cap = new_cap; Ok(()) @@ -737,7 +739,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> { // all 4GB in user-space. e.g., PAE or x32 #[inline] -fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { +fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize { Err(CapacityOverflow) } else { |
