Skip to content

Commit 5b1a046

Browse files
balt-devbalt-dev
authored andcommitted
Implement push_mut
1 parent 2b5e239 commit 5b1a046

File tree

3 files changed

+240
-27
lines changed

3 files changed

+240
-27
lines changed

library/alloc/src/collections/linked_list.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,11 +844,34 @@ impl<T, A: Allocator> LinkedList<T, A> {
844844
/// ```
845845
#[stable(feature = "rust1", since = "1.0.0")]
846846
pub fn push_front(&mut self, elt: T) {
847+
let _ = self.push_front_mut(elt);
848+
}
849+
850+
/// Adds an element first in the list, returning a reference to it.
851+
///
852+
/// This operation should compute in *O*(1) time.
853+
///
854+
/// # Examples
855+
///
856+
/// ```
857+
/// #![feature(push_mut)]
858+
/// use std::collections::LinkedList;
859+
///
860+
/// let mut dl = LinkedList::from([1, 2, 3]);
861+
///
862+
/// let ptr = dl.push_front_mut(2);
863+
/// *ptr += 4;
864+
/// assert_eq!(dl.front().unwrap(), &6);
865+
/// ```
866+
#[unstable(feature = "push_mut", issue = "135974")]
867+
#[must_use = "if you don't need a reference to the value, use `LinkedList::push_front` instead"]
868+
pub fn push_front_mut(&mut self, elt: T) -> &mut T {
847869
let node = Box::new_in(Node::new(elt), &self.alloc);
848-
let node_ptr = NonNull::from(Box::leak(node));
870+
let mut node_ptr = NonNull::from(Box::leak(node));
849871
// SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked
850872
unsafe {
851873
self.push_front_node(node_ptr);
874+
&mut node_ptr.as_mut().element
852875
}
853876
}
854877

@@ -893,11 +916,34 @@ impl<T, A: Allocator> LinkedList<T, A> {
893916
#[stable(feature = "rust1", since = "1.0.0")]
894917
#[rustc_confusables("push", "append")]
895918
pub fn push_back(&mut self, elt: T) {
919+
let _ = self.push_back_mut(elt);
920+
}
921+
922+
/// Adds an element to the back of a list, returning a reference to it.
923+
///
924+
/// This operation should compute in *O*(1) time.
925+
///
926+
/// # Examples
927+
///
928+
/// ```
929+
/// #![feature(push_mut)]
930+
/// use std::collections::LinkedList;
931+
///
932+
/// let mut dl = LinkedList::from([1, 2, 3]);
933+
///
934+
/// let ptr = dl.push_back_mut(2);
935+
/// *ptr += 4;
936+
/// assert_eq!(dl.back().unwrap(), &6);
937+
/// ```
938+
#[unstable(feature = "push_mut", issue = "135974")]
939+
#[must_use = "if you don't need a reference to the value, use `LinkedList::push_back` instead"]
940+
pub fn push_back_mut(&mut self, elt: T) -> &mut T {
896941
let node = Box::new_in(Node::new(elt), &self.alloc);
897-
let node_ptr = NonNull::from(Box::leak(node));
942+
let mut node_ptr = NonNull::from(Box::leak(node));
898943
// SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked
899944
unsafe {
900945
self.push_back_node(node_ptr);
946+
&mut node_ptr.as_mut().element
901947
}
902948
}
903949

library/alloc/src/collections/vec_deque/mod.rs

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,16 @@ impl<T, A: Allocator> VecDeque<T, A> {
182182
unsafe { ptr::read(self.ptr().add(off)) }
183183
}
184184

185-
/// Writes an element into the buffer, moving it.
185+
/// Writes an element into the buffer, moving it and returning a pointer to it.
186+
/// # Safety
187+
///
188+
/// May only be called if `off < self.capacity()`.
186189
#[inline]
187-
unsafe fn buffer_write(&mut self, off: usize, value: T) {
190+
unsafe fn buffer_write(&mut self, off: usize, value: T) -> &mut T {
188191
unsafe {
189-
ptr::write(self.ptr().add(off), value);
192+
let ptr = self.ptr().add(off);
193+
ptr::write(ptr, value);
194+
&mut *ptr
190195
}
191196
}
192197

@@ -1888,16 +1893,34 @@ impl<T, A: Allocator> VecDeque<T, A> {
18881893
#[stable(feature = "rust1", since = "1.0.0")]
18891894
#[track_caller]
18901895
pub fn push_front(&mut self, value: T) {
1896+
let _ = self.push_front_mut(value);
1897+
}
1898+
1899+
/// Prepends an element to the deque, returning a reference to it.
1900+
///
1901+
/// # Examples
1902+
///
1903+
/// ```
1904+
/// #![feature(push_mut)]
1905+
/// use std::collections::VecDeque;
1906+
///
1907+
/// let mut d = VecDeque::from([1, 2, 3]);
1908+
/// let x = d.push_front_mut(8);
1909+
/// *x -= 1;
1910+
/// assert_eq!(d.front(), Some(&7));
1911+
/// ```
1912+
#[unstable(feature = "push_mut", issue = "135974")]
1913+
#[track_caller]
1914+
#[must_use = "if you don't need a reference to the value, use `VecDeque::push_front` instead"]
1915+
pub fn push_front_mut(&mut self, value: T) -> &mut T {
18911916
if self.is_full() {
18921917
self.grow();
18931918
}
18941919

18951920
self.head = self.wrap_sub(self.head, 1);
18961921
self.len += 1;
1897-
1898-
unsafe {
1899-
self.buffer_write(self.head, value);
1900-
}
1922+
// SAFETY: We know that self.head is within range of the deque.
1923+
unsafe { self.buffer_write(self.head, value) }
19011924
}
19021925

19031926
/// Appends an element to the back of the deque.
@@ -1916,12 +1939,33 @@ impl<T, A: Allocator> VecDeque<T, A> {
19161939
#[rustc_confusables("push", "put", "append")]
19171940
#[track_caller]
19181941
pub fn push_back(&mut self, value: T) {
1942+
let _ = self.push_back_mut(value);
1943+
}
1944+
1945+
/// Appends an element to the back of the deque, returning a reference to it.
1946+
///
1947+
/// # Examples
1948+
///
1949+
/// ```
1950+
/// #![feature(push_mut)]
1951+
/// use std::collections::VecDeque;
1952+
///
1953+
/// let mut d = VecDeque::from([1, 2, 3]);
1954+
/// let x = d.push_back_mut(9);
1955+
/// *x += 1;
1956+
/// assert_eq!(d.back(), Some(&10));
1957+
/// ```
1958+
#[unstable(feature = "push_mut", issue = "135974")]
1959+
#[track_caller]
1960+
#[must_use = "if you don't need a reference to the value, use `VecDeque::push_back` instead"]
1961+
pub fn push_back_mut(&mut self, value: T) -> &mut T {
19191962
if self.is_full() {
19201963
self.grow();
19211964
}
19221965

1923-
unsafe { self.buffer_write(self.to_physical_idx(self.len), value) }
1966+
let len = self.len;
19241967
self.len += 1;
1968+
unsafe { self.buffer_write(self.to_physical_idx(len), value) }
19251969
}
19261970

19271971
#[inline]
@@ -2007,7 +2051,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
20072051
///
20082052
/// # Panics
20092053
///
2010-
/// Panics if `index` is strictly greater than deque's length
2054+
/// Panics if `index` is strictly greater than the deque's length.
20112055
///
20122056
/// # Examples
20132057
///
@@ -2029,7 +2073,37 @@ impl<T, A: Allocator> VecDeque<T, A> {
20292073
#[stable(feature = "deque_extras_15", since = "1.5.0")]
20302074
#[track_caller]
20312075
pub fn insert(&mut self, index: usize, value: T) {
2076+
let _ = self.insert_mut(index, value);
2077+
}
2078+
2079+
/// Inserts an element at `index` within the deque, shifting all elements
2080+
/// with indices greater than or equal to `index` towards the back, and
2081+
/// returning a reference to it.
2082+
///
2083+
/// Element at index 0 is the front of the queue.
2084+
///
2085+
/// # Panics
2086+
///
2087+
/// Panics if `index` is strictly greater than the deque's length.
2088+
///
2089+
/// # Examples
2090+
///
2091+
/// ```
2092+
/// #![feature(push_mut)]
2093+
/// use std::collections::VecDeque;
2094+
///
2095+
/// let mut vec_deque = VecDeque::from([1, 2, 3]);
2096+
///
2097+
/// let x = vec_deque.insert_mut(1, 5);
2098+
/// *x += 7;
2099+
/// assert_eq!(vec_deque, &[1, 12, 2, 3]);
2100+
/// ```
2101+
#[unstable(feature = "push_mut", issue = "135974")]
2102+
#[track_caller]
2103+
#[must_use = "if you don't need a reference to the value, use `VecDeque::insert` instead"]
2104+
pub fn insert_mut(&mut self, index: usize, value: T) -> &mut T {
20322105
assert!(index <= self.len(), "index out of bounds");
2106+
20332107
if self.is_full() {
20342108
self.grow();
20352109
}
@@ -2042,16 +2116,16 @@ impl<T, A: Allocator> VecDeque<T, A> {
20422116
unsafe {
20432117
// see `remove()` for explanation why this wrap_copy() call is safe.
20442118
self.wrap_copy(self.to_physical_idx(index), self.to_physical_idx(index + 1), k);
2045-
self.buffer_write(self.to_physical_idx(index), value);
20462119
self.len += 1;
2120+
self.buffer_write(self.to_physical_idx(index), value)
20472121
}
20482122
} else {
20492123
let old_head = self.head;
20502124
self.head = self.wrap_sub(self.head, 1);
20512125
unsafe {
20522126
self.wrap_copy(old_head, self.head, index);
2053-
self.buffer_write(self.to_physical_idx(index), value);
20542127
self.len += 1;
2128+
self.buffer_write(self.to_physical_idx(index), value)
20552129
}
20562130
}
20572131
}

library/alloc/src/vec/mod.rs

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,37 @@ impl<T, A: Allocator> Vec<T, A> {
20462046
#[stable(feature = "rust1", since = "1.0.0")]
20472047
#[track_caller]
20482048
pub fn insert(&mut self, index: usize, element: T) {
2049+
let _ = self.insert_mut(index, element);
2050+
}
2051+
2052+
/// Inserts an element at position `index` within the vector, shifting all
2053+
/// elements after it to the right.
2054+
///
2055+
/// # Panics
2056+
///
2057+
/// Panics if `index > len`.
2058+
///
2059+
/// # Examples
2060+
///
2061+
/// ```
2062+
/// #![feature(push_mut)]
2063+
/// let mut vec = vec![1, 3, 5, 9];
2064+
/// let x = vec.insert_mut(3, 6);
2065+
/// *x += 1;
2066+
/// assert_eq!(vec, [1, 3, 5, 7, 9]);
2067+
/// ```
2068+
///
2069+
/// # Time complexity
2070+
///
2071+
/// Takes *O*([`Vec::len`]) time. All items after the insertion index must be
2072+
/// shifted to the right. In the worst case, all elements are shifted when
2073+
/// the insertion index is 0.
2074+
#[cfg(not(no_global_oom_handling))]
2075+
#[inline]
2076+
#[unstable(feature = "push_mut", issue = "135974")]
2077+
#[track_caller]
2078+
#[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"]
2079+
pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
20492080
#[cold]
20502081
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
20512082
#[track_caller]
@@ -2067,8 +2098,8 @@ impl<T, A: Allocator> Vec<T, A> {
20672098
unsafe {
20682099
// infallible
20692100
// The spot to put the new value
2101+
let p = self.as_mut_ptr().add(index);
20702102
{
2071-
let p = self.as_mut_ptr().add(index);
20722103
if index < len {
20732104
// Shift everything over to make space. (Duplicating the
20742105
// `index`th element into two consecutive places.)
@@ -2079,6 +2110,7 @@ impl<T, A: Allocator> Vec<T, A> {
20792110
ptr::write(p, element);
20802111
}
20812112
self.set_len(len + 1);
2113+
&mut *p
20822114
}
20832115
}
20842116

@@ -2486,18 +2518,7 @@ impl<T, A: Allocator> Vec<T, A> {
24862518
#[rustc_confusables("push_back", "put", "append")]
24872519
#[track_caller]
24882520
pub fn push(&mut self, value: T) {
2489-
// Inform codegen that the length does not change across grow_one().
2490-
let len = self.len;
2491-
// This will panic or abort if we would allocate > isize::MAX bytes
2492-
// or if the length increment would overflow for zero-sized types.
2493-
if len == self.buf.capacity() {
2494-
self.buf.grow_one();
2495-
}
2496-
unsafe {
2497-
let end = self.as_mut_ptr().add(len);
2498-
ptr::write(end, value);
2499-
self.len = len + 1;
2500-
}
2521+
let _ = self.push_mut(value);
25012522
}
25022523

25032524
/// Appends an element if there is sufficient spare capacity, otherwise an error is returned
@@ -2538,15 +2559,87 @@ impl<T, A: Allocator> Vec<T, A> {
25382559
#[inline]
25392560
#[unstable(feature = "vec_push_within_capacity", issue = "100486")]
25402561
pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
2562+
self.push_mut_within_capacity(value).map(|_| ())
2563+
}
2564+
2565+
/// Appends an element to the back of a collection, returning a reference to it.
2566+
///
2567+
/// # Panics
2568+
///
2569+
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
2570+
///
2571+
/// # Examples
2572+
///
2573+
/// ```
2574+
/// #![feature(push_mut)]
2575+
///
2576+
///
2577+
/// let mut vec = vec![1, 2];
2578+
/// let last = vec.push_mut(3);
2579+
/// assert_eq!(*last, 3);
2580+
/// assert_eq!(vec, [1, 2, 3]);
2581+
///
2582+
/// let last = vec.push_mut(3);
2583+
/// *last += 1;
2584+
/// assert_eq!(vec, [1, 2, 3, 4]);
2585+
/// ```
2586+
///
2587+
/// # Time complexity
2588+
///
2589+
/// Takes amortized *O*(1) time. If the vector's length would exceed its
2590+
/// capacity after the push, *O*(*capacity*) time is taken to copy the
2591+
/// vector's elements to a larger allocation. This expensive operation is
2592+
/// offset by the *capacity* *O*(1) insertions it allows.
2593+
#[cfg(not(no_global_oom_handling))]
2594+
#[inline]
2595+
#[unstable(feature = "push_mut", issue = "135974")]
2596+
#[track_caller]
2597+
#[must_use = "if you don't need a reference to the value, use `Vec::push` instead"]
2598+
pub fn push_mut(&mut self, value: T) -> &mut T {
2599+
// Inform codegen that the length does not change across grow_one().
2600+
let len = self.len;
2601+
// This will panic or abort if we would allocate > isize::MAX bytes
2602+
// or if the length increment would overflow for zero-sized types.
2603+
if len == self.buf.capacity() {
2604+
self.buf.grow_one();
2605+
}
2606+
unsafe {
2607+
let end = self.as_mut_ptr().add(len);
2608+
ptr::write(end, value);
2609+
self.len = len + 1;
2610+
// SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference.
2611+
&mut *end
2612+
}
2613+
}
2614+
2615+
/// Appends an element and returns a reference to it if there is sufficient spare capacity,
2616+
/// otherwise an error is returned with the element.
2617+
///
2618+
/// Unlike [`push_mut`] this method will not reallocate when there's insufficient capacity.
2619+
/// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity.
2620+
///
2621+
/// [`push_mut`]: Vec::push_mut
2622+
/// [`reserve`]: Vec::reserve
2623+
/// [`try_reserve`]: Vec::try_reserve
2624+
///
2625+
/// # Time complexity
2626+
///
2627+
/// Takes *O*(1) time.
2628+
#[unstable(feature = "push_mut", issue = "135974")]
2629+
// #[unstable(feature = "vec_push_within_capacity", issue = "100486")]
2630+
#[inline]
2631+
#[must_use = "if you don't need a reference to the value, use `Vec::push_within_capacity` instead"]
2632+
pub fn push_mut_within_capacity(&mut self, value: T) -> Result<&mut T, T> {
25412633
if self.len == self.buf.capacity() {
25422634
return Err(value);
25432635
}
25442636
unsafe {
25452637
let end = self.as_mut_ptr().add(self.len);
25462638
ptr::write(end, value);
25472639
self.len += 1;
2640+
// SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference.
2641+
Ok(&mut *end)
25482642
}
2549-
Ok(())
25502643
}
25512644

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

0 commit comments

Comments
 (0)