Skip to content

Commit ed946fc

Browse files
author
baltdev
committed
Add push_mut
1 parent 1c9837d commit ed946fc

File tree

1 file changed

+70
-13
lines changed

1 file changed

+70
-13
lines changed

library/alloc/src/vec/mod.rs

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,18 +2414,7 @@ impl<T, A: Allocator> Vec<T, A> {
24142414
#[rustc_confusables("push_back", "put", "append")]
24152415
#[track_caller]
24162416
pub fn push(&mut self, value: T) {
2417-
// Inform codegen that the length does not change across grow_one().
2418-
let len = self.len;
2419-
// This will panic or abort if we would allocate > isize::MAX bytes
2420-
// or if the length increment would overflow for zero-sized types.
2421-
if len == self.buf.capacity() {
2422-
self.buf.grow_one();
2423-
}
2424-
unsafe {
2425-
let end = self.as_mut_ptr().add(len);
2426-
ptr::write(end, value);
2427-
self.len = len + 1;
2428-
}
2417+
let _ = self.push_mut(value);
24292418
}
24302419

24312420
/// Appends an element if there is sufficient spare capacity, otherwise an error is returned
@@ -2466,15 +2455,83 @@ impl<T, A: Allocator> Vec<T, A> {
24662455
#[inline]
24672456
#[unstable(feature = "vec_push_within_capacity", issue = "100486")]
24682457
pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
2458+
self.push_mut_within_capacity(value).map(|_| ())
2459+
}
2460+
2461+
/// Appends an element to the back of a collection, returning a reference to it.
2462+
///
2463+
/// # Panics
2464+
///
2465+
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
2466+
///
2467+
/// # Examples
2468+
///
2469+
/// ```
2470+
/// #![feature(push_mut)]
2471+
///
2472+
/// let mut vec = vec![];
2473+
/// // Polonius moment.
2474+
/// let last = if let Some(v) = vec.last_mut() { v } else { vec.push_mut(0) };
2475+
/// *last += 6;
2476+
/// assert_eq!(vec, [6]);
2477+
/// ```
2478+
///
2479+
/// # Time complexity
2480+
///
2481+
/// Takes amortized *O*(1) time. If the vector's length would exceed its
2482+
/// capacity after the push, *O*(*capacity*) time is taken to copy the
2483+
/// vector's elements to a larger allocation. This expensive operation is
2484+
/// offset by the *capacity* *O*(1) insertions it allows.
2485+
#[cfg(not(no_global_oom_handling))]
2486+
#[inline]
2487+
#[unstable(feature = "push_mut", issue = "none")]
2488+
#[track_caller]
2489+
#[must_use = "if you don't need a reference to the value, use Vec::push instead"]
2490+
pub fn push_mut(&mut self, value: T) -> &mut T {
2491+
// Inform codegen that the length does not change across grow_one().
2492+
let len = self.len;
2493+
// This will panic or abort if we would allocate > isize::MAX bytes
2494+
// or if the length increment would overflow for zero-sized types.
2495+
if len == self.buf.capacity() {
2496+
self.buf.grow_one();
2497+
}
2498+
unsafe {
2499+
let end = self.as_mut_ptr().add(len);
2500+
ptr::write(end, value);
2501+
self.len = len + 1;
2502+
// SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference.
2503+
&mut *end
2504+
}
2505+
}
2506+
2507+
/// Appends an element and returns a reference to it if there is sufficient spare capacity, otherwise an error is returned
2508+
/// with the element.
2509+
///
2510+
/// Unlike [`push_mut`] this method will not reallocate when there's insufficient capacity.
2511+
/// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity.
2512+
///
2513+
/// [`push_mut`]: Vec::push_mut
2514+
/// [`reserve`]: Vec::reserve
2515+
/// [`try_reserve`]: Vec::try_reserve
2516+
///
2517+
/// # Time complexity
2518+
///
2519+
/// Takes *O*(1) time.
2520+
#[inline]
2521+
#[unstable(feature = "push_mut", issue = "none")]
2522+
#[must_use = "if you don't need a reference to the value, use Vec::push_within_capacity instead"]
2523+
// #[unstable(feature = "vec_push_within_capacity", issue = "100486")]
2524+
pub fn push_mut_within_capacity(&mut self, value: T) -> Result<&mut T, T> {
24692525
if self.len == self.buf.capacity() {
24702526
return Err(value);
24712527
}
24722528
unsafe {
24732529
let end = self.as_mut_ptr().add(self.len);
24742530
ptr::write(end, value);
24752531
self.len += 1;
2532+
// SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference.
2533+
Ok(&mut *end)
24762534
}
2477-
Ok(())
24782535
}
24792536

24802537
/// Removes the last element from a vector and returns it, or [`None`] if it

0 commit comments

Comments
 (0)