Skip to content

Finalize the error type for try_reserve #61780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 16, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -1138,19 +1138,12 @@ dependencies = [

[[package]]
name = "hashbrown"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-alloc 1.0.0",
"rustc-std-workspace-core 1.0.0",
]

[[package]]
name = "hashbrown"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
]

@@ -3534,7 +3527,7 @@ dependencies = [
"core 0.0.0",
"dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
@@ -4450,7 +4443,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454"
"checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392"
"checksum handlebars 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
"checksum hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36"
"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
31 changes: 17 additions & 14 deletions src/liballoc/collections/mod.rs
Original file line number Diff line number Diff line change
@@ -41,32 +41,35 @@ pub use linked_list::LinkedList;
#[doc(no_inline)]
pub use vec_deque::VecDeque;

use crate::alloc::{AllocErr, LayoutErr};
use crate::alloc::{Layout, LayoutErr};

/// Augments `AllocErr` with a CapacityOverflow variant.
/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub enum CollectionAllocErr {
pub enum TryReserveError {
/// Error due to the computed capacity exceeding the collection's maximum
/// (usually `isize::MAX` bytes).
CapacityOverflow,
/// Error due to the allocator (see the `AllocErr` type's docs).
AllocErr,
}

#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
impl From<AllocErr> for CollectionAllocErr {
#[inline]
fn from(AllocErr: AllocErr) -> Self {
CollectionAllocErr::AllocErr
}
/// 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 CollectionAllocErr {
impl From<LayoutErr> for TryReserveError {
#[inline]
fn from(_: LayoutErr) -> Self {
CollectionAllocErr::CapacityOverflow
TryReserveError::CapacityOverflow
}
}

16 changes: 8 additions & 8 deletions src/liballoc/collections/vec_deque.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ use core::ptr::{self, NonNull};
use core::slice;
use core::hash::{Hash, Hasher};

use crate::collections::CollectionAllocErr;
use crate::collections::TryReserveError;
use crate::raw_vec::RawVec;
use crate::vec::Vec;

@@ -576,10 +576,10 @@ impl<T> VecDeque<T> {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
/// use std::collections::VecDeque;
///
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> {
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> {
/// let mut output = VecDeque::new();
///
/// // Pre-reserve the memory, exiting if we can't
@@ -595,7 +595,7 @@ impl<T> VecDeque<T> {
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.try_reserve(additional)
}

@@ -614,10 +614,10 @@ impl<T> VecDeque<T> {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
/// use std::collections::VecDeque;
///
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> {
/// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> {
/// let mut output = VecDeque::new();
///
/// // Pre-reserve the memory, exiting if we can't
@@ -633,12 +633,12 @@ impl<T> VecDeque<T> {
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
let old_cap = self.cap();
let used_cap = self.len() + 1;
let new_cap = used_cap.checked_add(additional)
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
.ok_or(CollectionAllocErr::CapacityOverflow)?;
.ok_or(TryReserveError::CapacityOverflow)?;

if new_cap > old_cap {
self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?;
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
@@ -87,6 +87,7 @@
#![feature(const_in_array_repeat_expressions)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
#![feature(container_error_extra)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(fmt_internals)]
32 changes: 17 additions & 15 deletions src/liballoc/raw_vec.rs
Original file line number Diff line number Diff line change
@@ -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 {
14 changes: 7 additions & 7 deletions src/liballoc/string.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ use core::ptr;
use core::str::{pattern::Pattern, lossy};

use crate::borrow::{Cow, ToOwned};
use crate::collections::CollectionAllocErr;
use crate::collections::TryReserveError;
use crate::boxed::Box;
use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
use crate::vec::Vec;
@@ -937,9 +937,9 @@ impl String {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &str) -> Result<String, CollectionAllocErr> {
/// fn process_data(data: &str) -> Result<String, TryReserveError> {
/// let mut output = String::new();
///
/// // Pre-reserve the memory, exiting if we can't
@@ -953,7 +953,7 @@ impl String {
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve(additional)
}

@@ -975,9 +975,9 @@ impl String {
///
/// ```
/// #![feature(try_reserve)]
/// use std::collections::CollectionAllocErr;
/// use std::collections::TryReserveError;
///
/// fn process_data(data: &str) -> Result<String, CollectionAllocErr> {
/// fn process_data(data: &str) -> Result<String, TryReserveError> {
/// let mut output = String::new();
///
/// // Pre-reserve the memory, exiting if we can't
@@ -991,7 +991,7 @@ impl String {
/// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?");
/// ```
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.vec.try_reserve_exact(additional)
}

14 changes: 7 additions & 7 deletions src/liballoc/tests/string.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::borrow::Cow;
use std::collections::CollectionAllocErr::*;
use std::collections::TryReserveError::*;
use std::mem::size_of;
use std::{usize, isize};

@@ -566,11 +566,11 @@ fn test_try_reserve() {
} else { panic!("usize::MAX should trigger an overflow!") }
} else {
// Check isize::MAX + 1 is an OOM
if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) {
if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }

// Check usize::MAX is an OOM
if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) {
if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an OOM!") }
}
}
@@ -590,7 +590,7 @@ fn test_try_reserve() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
// Should always overflow in the add-to-len
@@ -629,10 +629,10 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") }
} else {
if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) {
if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }

if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) {
if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an OOM!") }
}
}
@@ -651,7 +651,7 @@ fn test_try_reserve_exact() {
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); }
} else {
if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
Loading