Skip to content

Commit 313490a

Browse files
committed
Dedup regular methods from new try_ ones
I did all the non-specialization trait ones. I hope this doesn't cause performance issues
1 parent 50959c4 commit 313490a

File tree

5 files changed

+73
-138
lines changed

5 files changed

+73
-138
lines changed

library/alloc/src/collections/mod.rs

+17
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ pub use linked_list::LinkedList;
5252
#[doc(no_inline)]
5353
pub use vec_deque::VecDeque;
5454

55+
#[cfg(not(no_global_oom_handling))]
56+
use crate::alloc::handle_alloc_error;
5557
use crate::alloc::{Layout, LayoutError};
58+
#[cfg(not(no_global_oom_handling))]
59+
use crate::raw_vec::capacity_overflow;
5660
use core::fmt::Display;
5761

5862
/// The error type for `try_reserve` methods.
@@ -105,6 +109,19 @@ pub enum TryReserveErrorKind {
105109
},
106110
}
107111

112+
#[cfg(not(no_global_oom_handling))]
113+
impl TryReserveError {
114+
/// Panic, or worse, according to the global handlers for each case.
115+
pub(crate) fn handle(self) -> ! {
116+
match self {
117+
TryReserveErrorKind::CapacityOverflow => capacity_overflow(),
118+
TryReserveErrorKind::AllocError { layout, non_exhaustive: () } => {
119+
handle_alloc_error(layout)
120+
}
121+
}
122+
}
123+
}
124+
108125
#[unstable(
109126
feature = "try_reserve_kind",
110127
reason = "Uncertain how much info should be exposed",

library/alloc/src/raw_vec.rs

+18-46
Original file line numberDiff line numberDiff line change
@@ -206,33 +206,9 @@ impl<T, A: Allocator> RawVec<T, A> {
206206

207207
#[cfg(not(no_global_oom_handling))]
208208
fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
209-
if mem::size_of::<T>() == 0 {
210-
Self::new_in(alloc)
211-
} else {
212-
// We avoid `unwrap_or_else` here because it bloats the amount of
213-
// LLVM IR generated.
214-
let layout = match Layout::array::<T>(capacity) {
215-
Ok(layout) => layout,
216-
Err(_) => capacity_overflow(),
217-
};
218-
match alloc_guard(layout.size()) {
219-
Ok(_) => {}
220-
Err(_) => capacity_overflow(),
221-
}
222-
let result = match init {
223-
AllocInit::Uninitialized => alloc.allocate(layout),
224-
AllocInit::Zeroed => alloc.allocate_zeroed(layout),
225-
};
226-
let ptr = match result {
227-
Ok(ptr) => ptr,
228-
Err(_) => handle_alloc_error(layout),
229-
};
230-
231-
Self {
232-
ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) },
233-
cap: Self::capacity_from_bytes(ptr.len()),
234-
alloc,
235-
}
209+
match Self::try_allocate_in(capacity, init, alloc) {
210+
Ok(r) => r,
211+
Err(e) => e.handle(),
236212
}
237213
}
238214

@@ -437,7 +413,7 @@ impl<T, A: Allocator> RawVec<T, A> {
437413
/// Aborts on OOM.
438414
#[cfg(not(no_global_oom_handling))]
439415
pub fn shrink_to_fit(&mut self, amount: usize) {
440-
handle_reserve(self.shrink(amount));
416+
handle_reserve(self.try_shrink_to_fit(amount));
441417
}
442418

443419
/// Tries to shrink the allocation down to the specified amount. If the given amount
@@ -447,7 +423,19 @@ impl<T, A: Allocator> RawVec<T, A> {
447423
///
448424
/// Panics if the given amount is *larger* than the current capacity.
449425
pub fn try_shrink_to_fit(&mut self, amount: usize) -> Result<(), TryReserveError> {
450-
self.shrink(amount)
426+
assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity");
427+
428+
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
429+
let new_size = amount * mem::size_of::<T>();
430+
431+
let ptr = unsafe {
432+
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
433+
self.alloc
434+
.shrink(ptr, layout, new_layout)
435+
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
436+
};
437+
self.set_ptr(ptr);
438+
Ok(())
451439
}
452440
}
453441

@@ -519,22 +507,6 @@ impl<T, A: Allocator> RawVec<T, A> {
519507
self.set_ptr(ptr);
520508
Ok(())
521509
}
522-
523-
fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> {
524-
assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity");
525-
526-
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
527-
let new_size = amount * mem::size_of::<T>();
528-
529-
let ptr = unsafe {
530-
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
531-
self.alloc
532-
.shrink(ptr, layout, new_layout)
533-
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
534-
};
535-
self.set_ptr(ptr);
536-
Ok(())
537-
}
538510
}
539511

540512
// This function is outside `RawVec` to minimize compile times. See the comment
@@ -611,6 +583,6 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
611583
// ensure that the code generation related to these panics is minimal as there's
612584
// only one location which panics rather than a bunch throughout the module.
613585
#[cfg(not(no_global_oom_handling))]
614-
fn capacity_overflow() -> ! {
586+
pub(crate) fn capacity_overflow() -> ! {
615587
panic!("capacity overflow");
616588
}

library/alloc/src/string.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@
4646
use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
4747
use core::fmt;
4848
use core::hash;
49+
use core::iter::FusedIterator;
4950
#[cfg(not(no_global_oom_handling))]
50-
use core::iter::FromIterator;
51-
use core::iter::{from_fn, FusedIterator};
51+
use core::iter::{from_fn, FromIterator};
5252
#[cfg(not(no_global_oom_handling))]
5353
use core::ops::Add;
5454
#[cfg(not(no_global_oom_handling))]

library/alloc/src/sync.rs

+12-18
Original file line numberDiff line numberDiff line change
@@ -1199,11 +1199,10 @@ impl<T> Arc<[T]> {
11991199
#[cfg(not(no_global_oom_handling))]
12001200
unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> {
12011201
unsafe {
1202-
Self::allocate_for_layout(
1203-
Layout::array::<T>(len).unwrap(),
1204-
|layout| Global.allocate(layout),
1205-
|mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>,
1206-
)
1202+
match Self::try_allocate_for_slice(len) {
1203+
Ok(r) => r,
1204+
Err(e) => e.handle(),
1205+
}
12071206
}
12081207
}
12091208

@@ -1226,11 +1225,10 @@ impl<T> Arc<[T]> {
12261225
#[cfg(not(no_global_oom_handling))]
12271226
unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
12281227
unsafe {
1229-
let ptr = Self::allocate_for_slice(v.len());
1230-
1231-
ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).data as *mut [T] as *mut T, v.len());
1232-
1233-
Self::from_ptr(ptr)
1228+
match Self::try_copy_from_slice(v) {
1229+
Ok(r) => r,
1230+
Err(e) => e.handle(),
1231+
}
12341232
}
12351233
}
12361234

@@ -2484,14 +2482,10 @@ impl<T> From<Vec<T>> for Arc<[T]> {
24842482
/// assert_eq!(&[1, 2, 3], &shared[..]);
24852483
/// ```
24862484
#[inline]
2487-
fn from(mut v: Vec<T>) -> Arc<[T]> {
2488-
unsafe {
2489-
let arc = Arc::copy_from_slice(&v);
2490-
2491-
// Allow the Vec to free its memory, but not destroy its contents
2492-
v.set_len(0);
2493-
2494-
arc
2485+
fn from(v: Vec<T>) -> Arc<[T]> {
2486+
match Arc::try_from_vec(v) {
2487+
Ok(r) => r,
2488+
Err(e) => e.handle(),
24952489
}
24962490
}
24972491
}

library/alloc/src/vec/mod.rs

+24-72
Original file line numberDiff line numberDiff line change
@@ -1023,11 +1023,9 @@ impl<T, A: Allocator> Vec<T, A> {
10231023
#[cfg(not(no_global_oom_handling))]
10241024
#[stable(feature = "rust1", since = "1.0.0")]
10251025
pub fn shrink_to_fit(&mut self) {
1026-
// The capacity is never less than the length, and there's nothing to do when
1027-
// they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit`
1028-
// by only calling it with a greater capacity.
1029-
if self.capacity() > self.len {
1030-
self.buf.shrink_to_fit(self.len);
1026+
match self.try_shrink_to_fit() {
1027+
Ok(r) => r,
1028+
Err(e) => e.handle(),
10311029
}
10321030
}
10331031

@@ -1110,13 +1108,10 @@ impl<T, A: Allocator> Vec<T, A> {
11101108
/// ```
11111109
#[cfg(not(no_global_oom_handling))]
11121110
#[stable(feature = "rust1", since = "1.0.0")]
1113-
pub fn into_boxed_slice(mut self) -> Box<[T], A> {
1114-
unsafe {
1115-
self.shrink_to_fit();
1116-
let me = ManuallyDrop::new(self);
1117-
let buf = ptr::read(&me.buf);
1118-
let len = me.len();
1119-
buf.into_box(len).assume_init()
1111+
pub fn into_boxed_slice(self) -> Box<[T], A> {
1112+
match self.try_into_boxed_slice() {
1113+
Ok(r) => r,
1114+
Err(e) => e.handle(),
11201115
}
11211116
}
11221117

@@ -1844,15 +1839,9 @@ impl<T, A: Allocator> Vec<T, A> {
18441839
#[inline]
18451840
#[stable(feature = "rust1", since = "1.0.0")]
18461841
pub fn push(&mut self, value: T) {
1847-
// This will panic or abort if we would allocate > isize::MAX bytes
1848-
// or if the length increment would overflow for zero-sized types.
1849-
if self.len == self.buf.capacity() {
1850-
self.reserve(1);
1851-
}
1852-
unsafe {
1853-
let end = self.as_mut_ptr().add(self.len);
1854-
ptr::write(end, value);
1855-
self.len += 1;
1842+
match self.try_push(value) {
1843+
Ok(r) => r,
1844+
Err(e) => e.handle(),
18561845
}
18571846
}
18581847

@@ -1931,11 +1920,12 @@ impl<T, A: Allocator> Vec<T, A> {
19311920
#[cfg(not(no_global_oom_handling))]
19321921
#[inline]
19331922
unsafe fn append_elements(&mut self, other: *const [T]) {
1934-
let count = unsafe { (*other).len() };
1935-
self.reserve(count);
1936-
let len = self.len();
1937-
unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) };
1938-
self.len += count;
1923+
unsafe {
1924+
match self.try_append_elements(other) {
1925+
Ok(r) => r,
1926+
Err(e) => e.handle(),
1927+
}
1928+
}
19391929
}
19401930

19411931
/// Tries to append elements to `Self` from other buffer.
@@ -2515,31 +2505,10 @@ impl<T, F: FnMut() -> T> ExtendWith<T> for ExtendFunc<F> {
25152505
impl<T, A: Allocator> Vec<T, A> {
25162506
#[cfg(not(no_global_oom_handling))]
25172507
/// Extend the vector by `n` values, using the given generator.
2518-
fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) {
2519-
self.reserve(n);
2520-
2521-
unsafe {
2522-
let mut ptr = self.as_mut_ptr().add(self.len());
2523-
// Use SetLenOnDrop to work around bug where compiler
2524-
// might not realize the store through `ptr` through self.set_len()
2525-
// don't alias.
2526-
let mut local_len = SetLenOnDrop::new(&mut self.len);
2527-
2528-
// Write all elements except the last one
2529-
for _ in 1..n {
2530-
ptr::write(ptr, value.next());
2531-
ptr = ptr.offset(1);
2532-
// Increment the length in every step in case next() panics
2533-
local_len.increment_len(1);
2534-
}
2535-
2536-
if n > 0 {
2537-
// We can write the last element directly without cloning needlessly
2538-
ptr::write(ptr, value.last());
2539-
local_len.increment_len(1);
2540-
}
2541-
2542-
// len set by scope guard
2508+
fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, value: E) {
2509+
match self.try_extend_with(n, value) {
2510+
Ok(r) => r,
2511+
Err(e) => e.handle(),
25432512
}
25442513
}
25452514

@@ -2886,27 +2855,10 @@ impl<T, A: Allocator> Vec<T, A> {
28862855
// leaf method to which various SpecFrom/SpecExtend implementations delegate when
28872856
// they have no further optimizations to apply
28882857
#[cfg(not(no_global_oom_handling))]
2889-
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
2890-
// This is the case for a general iterator.
2891-
//
2892-
// This function should be the moral equivalent of:
2893-
//
2894-
// for item in iterator {
2895-
// self.push(item);
2896-
// }
2897-
while let Some(element) = iterator.next() {
2898-
let len = self.len();
2899-
if len == self.capacity() {
2900-
let (lower, _) = iterator.size_hint();
2901-
self.reserve(lower.saturating_add(1));
2902-
}
2903-
unsafe {
2904-
ptr::write(self.as_mut_ptr().add(len), element);
2905-
// Since next() executes user code which can panic we have to bump the length
2906-
// after each step.
2907-
// NB can't overflow since we would have had to alloc the address space
2908-
self.set_len(len + 1);
2909-
}
2858+
fn extend_desugared<I: Iterator<Item = T>>(&mut self, iterator: I) {
2859+
match self.try_extend_desugared(iterator) {
2860+
Ok(r) => r,
2861+
Err(e) => e.handle(),
29102862
}
29112863
}
29122864

0 commit comments

Comments
 (0)