mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Add try_shrink_to and try_shrink_to_fit to Vec
* Add try_shrink_to and try_shrink_to_fit to Vec Both functions are required to support shrinking a vector in environments without global OOM handling. * Format the try_shrink functions * Remove excess "```" from doc * Remove `cfg(not(no_global_oom_handling))` from rawvecinner::shrink * Fix import cmp even if no_global_oom_handling is defined
This commit is contained in:
@@ -399,6 +399,21 @@ pub(crate) fn shrink_to_fit(&mut self, cap: usize) {
|
||||
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
|
||||
unsafe { self.inner.shrink_to_fit(cap, T::LAYOUT) }
|
||||
}
|
||||
|
||||
/// Shrinks the buffer down to the specified capacity. If the given amount
|
||||
/// is 0, actually completely deallocates.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function returns an error if the allocator cannot shrink the allocation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the given amount is *larger* than the current capacity.
|
||||
#[inline]
|
||||
pub(crate) fn try_shrink_to_fit(&mut self, cap: usize) -> Result<(), TryReserveError> {
|
||||
unsafe { self.inner.try_shrink_to_fit(cap, T::LAYOUT) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
|
||||
@@ -731,6 +746,20 @@ unsafe fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
|
||||
/// initially construct `self`
|
||||
/// - `elem_layout`'s size must be a multiple of its alignment
|
||||
/// - `cap` must be less than or equal to `self.capacity(elem_layout.size())`
|
||||
unsafe fn try_shrink_to_fit(
|
||||
&mut self,
|
||||
cap: usize,
|
||||
elem_layout: Layout,
|
||||
) -> Result<(), TryReserveError> {
|
||||
unsafe { self.shrink(cap, elem_layout) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const fn needs_to_grow(&self, len: usize, additional: usize, elem_layout: Layout) -> bool {
|
||||
additional > self.capacity(elem_layout.size()).wrapping_sub(len)
|
||||
@@ -778,7 +807,6 @@ unsafe fn grow_exact(
|
||||
/// initially construct `self`
|
||||
/// - `elem_layout`'s size must be a multiple of its alignment
|
||||
/// - `cap` must be less than or equal to `self.capacity(elem_layout.size())`
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
unsafe fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryReserveError> {
|
||||
assert!(cap <= self.capacity(elem_layout.size()), "Tried to shrink to a larger capacity");
|
||||
@@ -796,7 +824,6 @@ unsafe fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryRe
|
||||
///
|
||||
/// # Safety
|
||||
/// `cap <= self.capacity()`
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
unsafe fn shrink_unchecked(
|
||||
&mut self,
|
||||
cap: usize,
|
||||
|
||||
@@ -75,8 +75,6 @@
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::TrivialClone;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::cmp;
|
||||
use core::cmp::Ordering;
|
||||
use core::hash::{Hash, Hasher};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
@@ -88,7 +86,7 @@
|
||||
use core::ops::{self, Index, IndexMut, Range, RangeBounds};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::slice::{self, SliceIndex};
|
||||
use core::{fmt, hint, intrinsics, ub_checks};
|
||||
use core::{cmp, fmt, hint, intrinsics, ub_checks};
|
||||
|
||||
#[stable(feature = "extract_if", since = "1.87.0")]
|
||||
pub use self::extract_if::ExtractIf;
|
||||
@@ -1613,6 +1611,73 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to shrink the capacity of the vector as much as possible
|
||||
///
|
||||
/// The behavior of this method depends on the allocator, which may either shrink the vector
|
||||
/// in-place or reallocate. The resulting vector might still have some excess capacity, just as
|
||||
/// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details.
|
||||
///
|
||||
/// [`with_capacity`]: Vec::with_capacity
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function returns an error if the allocator fails to shrink the allocation,
|
||||
/// the vector thereafter is still safe to use, the capacity remains unchanged
|
||||
/// however. See [`Allocator::shrink`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vec_fallible_shrink)]
|
||||
///
|
||||
/// let mut vec = Vec::with_capacity(10);
|
||||
/// vec.extend([1, 2, 3]);
|
||||
/// assert!(vec.capacity() >= 10);
|
||||
/// vec.try_shrink_to_fit().expect("why is the test harness failing to shrink to 12 bytes");
|
||||
/// assert!(vec.capacity() >= 3);
|
||||
/// ```
|
||||
#[unstable(feature = "vec_fallible_shrink", issue = "152350")]
|
||||
#[inline]
|
||||
pub fn try_shrink_to_fit(&mut self) -> Result<(), TryReserveError> {
|
||||
if self.capacity() > self.len { self.buf.try_shrink_to_fit(self.len) } else { Ok(()) }
|
||||
}
|
||||
|
||||
/// Shrinks the capacity of the vector with a lower bound.
|
||||
///
|
||||
/// The capacity will remain at least as large as both the length
|
||||
/// and the supplied value.
|
||||
///
|
||||
/// If the current capacity is less than the lower limit, this is a no-op.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function returns an error if the allocator fails to shrink the allocation,
|
||||
/// the vector thereafter is still safe to use, the capacity remains unchanged
|
||||
/// however. See [`Allocator::shrink`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vec_fallible_shrink)]
|
||||
///
|
||||
/// let mut vec = Vec::with_capacity(10);
|
||||
/// vec.extend([1, 2, 3]);
|
||||
/// assert!(vec.capacity() >= 10);
|
||||
/// vec.try_shrink_to(4).expect("why is the test harness failing to shrink to 12 bytes");
|
||||
/// assert!(vec.capacity() >= 4);
|
||||
/// vec.try_shrink_to(0).expect("this is a no-op and thus the allocator isn't involved.");
|
||||
/// assert!(vec.capacity() >= 3);
|
||||
/// ```
|
||||
#[unstable(feature = "vec_fallible_shrink", issue = "152350")]
|
||||
#[inline]
|
||||
pub fn try_shrink_to(&mut self, min_capacity: usize) -> Result<(), TryReserveError> {
|
||||
if self.capacity() > min_capacity {
|
||||
self.buf.try_shrink_to_fit(cmp::max(self.len, min_capacity))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the vector into [`Box<[T]>`][owned slice].
|
||||
///
|
||||
/// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`].
|
||||
|
||||
Reference in New Issue
Block a user