Skip to content

Commit 1a7c203

Browse files
committed
Auto merge of rust-lang#89123 - the8472:push_in_capacity, r=amanieu
add Vec::push_within_capacity - fallible, does not allocate This method can serve several purposes. It * is fallible * guarantees that items in Vec aren't moved * allows loops that do `reserve` and `push` separately to avoid pulling in the allocation machinery a second time in the `push` part which should make things easier on the optimizer * eases the path towards `ArrayVec` a bit since - compared to `push()` - there are fewer questions around how it should be implemented I haven't named it `try_push` because that should probably occupy a middle ground that will still try to reserve and only return an error in the unlikely OOM case. resolves rust-lang#84649
2 parents 81f3919 + bb74f97 commit 1a7c203

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

library/alloc/src/vec/mod.rs

+45
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,51 @@ impl<T, A: Allocator> Vec<T, A> {
18391839
}
18401840
}
18411841

1842+
/// Appends an element if there is sufficient spare capacity, otherwise an error is returned
1843+
/// with the element.
1844+
///
1845+
/// Unlike [`push`] this method will not reallocate when there's insufficient capacity.
1846+
/// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity.
1847+
///
1848+
/// [`push`]: Vec::push
1849+
/// [`reserve`]: Vec::reserve
1850+
/// [`try_reserve`]: Vec::try_reserve
1851+
///
1852+
/// # Examples
1853+
///
1854+
/// A manual, panic-free alternative to [`FromIterator`]:
1855+
///
1856+
/// ```
1857+
/// #![feature(vec_push_within_capacity)]
1858+
///
1859+
/// use std::collections::TryReserveError;
1860+
/// fn from_iter_fallible<T>(iter: impl Iterator<Item=T>) -> Result<Vec<T>, TryReserveError> {
1861+
/// let mut vec = Vec::new();
1862+
/// for value in iter {
1863+
/// if let Err(value) = vec.push_within_capacity(value) {
1864+
/// vec.try_reserve(1)?;
1865+
/// // this cannot fail, the previous line either returned or added at least 1 free slot
1866+
/// let _ = vec.push_within_capacity(value);
1867+
/// }
1868+
/// }
1869+
/// Ok(vec)
1870+
/// }
1871+
/// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100)));
1872+
/// ```
1873+
#[inline]
1874+
#[unstable(feature = "vec_push_within_capacity", issue = "100486")]
1875+
pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
1876+
if self.len == self.buf.capacity() {
1877+
return Err(value);
1878+
}
1879+
unsafe {
1880+
let end = self.as_mut_ptr().add(self.len);
1881+
ptr::write(end, value);
1882+
self.len += 1;
1883+
}
1884+
Ok(())
1885+
}
1886+
18421887
/// Removes the last element from a vector and returns it, or [`None`] if it
18431888
/// is empty.
18441889
///

0 commit comments

Comments
 (0)