Skip to content

Commit 4289449

Browse files
author
balt-dev
committed
insert_mut, and friends
1 parent 8c94587 commit 4289449

File tree

3 files changed

+229
-7
lines changed

3 files changed

+229
-7
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 last in the 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: 120 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,13 @@ 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.
186186
#[inline]
187-
unsafe fn buffer_write(&mut self, off: usize, value: T) {
187+
unsafe fn buffer_write(&mut self, off: usize, value: T) -> *mut T {
188188
unsafe {
189-
ptr::write(self.ptr().add(off), value);
189+
let ptr = self.ptr().add(off);
190+
ptr::write(ptr, value);
191+
ptr
190192
}
191193
}
192194

@@ -1920,10 +1922,66 @@ impl<T, A: Allocator> VecDeque<T, A> {
19201922
self.grow();
19211923
}
19221924

1923-
unsafe { self.buffer_write(self.to_physical_idx(self.len), value) }
1925+
unsafe { self.buffer_write(self.to_physical_idx(self.len), value) };
19241926
self.len += 1;
19251927
}
19261928

1929+
/// Prepends an element to the deque, returning a reference to it.
1930+
///
1931+
/// # Examples
1932+
///
1933+
/// ```
1934+
/// #![feature(push_mut)]
1935+
/// use std::collections::VecDeque;
1936+
///
1937+
/// let mut d = VecDeque::from([1, 2, 3]);
1938+
/// let x = d.push_front_mut(1);
1939+
/// *x -= 1;
1940+
/// assert_eq!(d.front(), Some(&0));
1941+
/// ```
1942+
#[unstable(feature = "push_mut", issue = "135974")]
1943+
#[track_caller]
1944+
#[must_use = "if you don't need a reference to the value, use VecDeque::push_front instead"]
1945+
pub fn push_front_mut(&mut self, value: T) -> &mut T {
1946+
if self.is_full() {
1947+
self.grow();
1948+
}
1949+
1950+
self.head = self.wrap_sub(self.head, 1);
1951+
self.len += 1;
1952+
1953+
unsafe {
1954+
let ptr = self.buffer_write(self.head, value);
1955+
&mut *ptr
1956+
}
1957+
}
1958+
1959+
/// Appends an element to the back of the deque, returning a reference to it.
1960+
///
1961+
/// # Examples
1962+
///
1963+
/// ```
1964+
/// #![feature(push_mut)]
1965+
/// use std::collections::VecDeque;
1966+
///
1967+
/// let mut d = VecDeque::from([1, 2, 3]);
1968+
/// let x = d.push_back_mut(3);
1969+
/// *x += 1;
1970+
/// assert_eq!(d.back(), Some(&4));
1971+
/// ```
1972+
#[unstable(feature = "push_mut", issue = "135974")]
1973+
#[track_caller]
1974+
#[must_use = "if you don't need a reference to the value, use VecDeque::push_back instead"]
1975+
pub fn push_back_mut(&mut self, value: T) -> &mut T {
1976+
if self.is_full() {
1977+
self.grow();
1978+
}
1979+
1980+
let back_ptr = unsafe { self.buffer_write(self.to_physical_idx(self.len), value) };
1981+
self.len += 1;
1982+
unsafe { &mut *back_ptr }
1983+
}
1984+
19271985
#[inline]
19281986
fn is_contiguous(&self) -> bool {
19291987
// Do the calculation like this to avoid overflowing if len + head > usize::MAX
@@ -2056,6 +2114,64 @@ impl<T, A: Allocator> VecDeque<T, A> {
20562114
}
20572115
}
20582116

2117+
/// Inserts an element at `index` within the deque, shifting all elements
2118+
/// with indices greater than or equal to `index` towards the back,
2119+
/// and returning a reference to it.
2120+
///
2121+
/// Element at index 0 is the front of the queue.
2122+
///
2123+
/// Returns [`None`] if `index` is strictly greater than deque's length.
2124+
///
2125+
/// # Examples
2126+
///
2127+
/// ```
2128+
/// #![feature(push_mut)]
2129+
/// use std::collections::VecDeque;
2130+
///
2131+
/// let mut vec_deque = VecDeque::from([1, 2, 3]);
2132+
///
2133+
/// let x = vec_deque.insert_mut(1, 5).unwrap();
2134+
/// *x += 7;
2135+
/// assert_eq!(vec_deque, &[1, 12, 2, 3]);
2136+
///
2137+
/// let y = vec_deque.insert_mut(7, 5);
2138+
/// assert!(y.is_none());
2139+
/// ```
2140+
#[unstable(feature = "push_mut", issue = "135974")]
2141+
#[track_caller]
2142+
#[must_use = "if you don't need a reference to the value or type-safe bound checking, use VecDeque::insert instead"]
2143+
pub fn insert_mut(&mut self, index: usize, value: T) -> Option<&mut T> {
2144+
if index > self.len() {
2145+
return None;
2146+
}
2147+
if self.is_full() {
2148+
self.grow();
2149+
}
2150+
2151+
let k = self.len - index;
2152+
if k < index {
2153+
// `index + 1` can't overflow, because if index was usize::MAX, then either the
2154+
// assert would've failed, or the deque would've tried to grow past usize::MAX
2155+
// and panicked.
2156+
unsafe {
2157+
// see `remove()` for explanation why this wrap_copy() call is safe.
2158+
self.wrap_copy(self.to_physical_idx(index), self.to_physical_idx(index + 1), k);
2159+
let ptr = self.buffer_write(self.to_physical_idx(index), value);
2160+
self.len += 1;
2161+
Some(&mut *ptr)
2162+
}
2163+
} else {
2164+
let old_head = self.head;
2165+
self.head = self.wrap_sub(self.head, 1);
2166+
unsafe {
2167+
self.wrap_copy(old_head, self.head, index);
2168+
let ptr = self.buffer_write(self.to_physical_idx(index), value);
2169+
self.len += 1;
2170+
Some(&mut *ptr)
2171+
}
2172+
}
2173+
}
2174+
20592175
/// Removes and returns the element at `index` from the deque.
20602176
/// Whichever end is closer to the removal point will be moved to make
20612177
/// room, and all the affected elements will be moved to new positions.

library/alloc/src/vec/mod.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1974,6 +1974,8 @@ impl<T, A: Allocator> Vec<T, A> {
19741974
}
19751975
}
19761976

1977+
1978+
19771979
/// Inserts an element at position `index` within the vector, shifting all
19781980
/// elements after it to the right.
19791981
///
@@ -2000,7 +2002,7 @@ impl<T, A: Allocator> Vec<T, A> {
20002002
#[stable(feature = "rust1", since = "1.0.0")]
20012003
#[track_caller]
20022004
pub fn insert(&mut self, index: usize, element: T) {
2003-
#[cold]
2005+
#[cold]
20042006
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
20052007
#[track_caller]
20062008
#[optimize(size)]
@@ -2036,6 +2038,64 @@ impl<T, A: Allocator> Vec<T, A> {
20362038
}
20372039
}
20382040

2041+
/// Inserts an element at position `index` within the vector, shifting all
2042+
/// elements after it to the right.
2043+
///
2044+
/// Returns [`None`] if the specified index is out of bounds.
2045+
///
2046+
/// # Examples
2047+
///
2048+
/// ```
2049+
/// #![feature(push_mut)]
2050+
/// let mut vec = vec![1, 3, 5, 9];
2051+
/// let x = vec.insert_mut(3, 6).unwrap();
2052+
/// *x += 1;
2053+
/// assert_eq!(vec, [1, 3, 5, 7, 9]);
2054+
///
2055+
/// let y = vec.insert_mut(7, 6);
2056+
/// assert!(y.is_none());
2057+
/// ```
2058+
///
2059+
/// # Time complexity
2060+
///
2061+
/// Takes *O*([`Vec::len`]) time. All items after the insertion index must be
2062+
/// shifted to the right. In the worst case, all elements are shifted when
2063+
/// the insertion index is 0.
2064+
#[cfg(not(no_global_oom_handling))]
2065+
#[inline]
2066+
#[unstable(feature = "push_mut", issue = "135974")]
2067+
#[track_caller]
2068+
#[must_use = "if you don't need a reference to the value or type-safe bound checking, use Vec::insert instead"]
2069+
pub fn insert_mut(&mut self, index: usize, element: T) -> Option<&mut T> {
2070+
let len = self.len();
2071+
if index > len {
2072+
return None;
2073+
}
2074+
2075+
// space for the new element
2076+
if len == self.buf.capacity() {
2077+
self.buf.grow_one();
2078+
}
2079+
2080+
unsafe {
2081+
// infallible
2082+
// The spot to put the new value
2083+
let p = self.as_mut_ptr().add(index);
2084+
{
2085+
if index < len {
2086+
// Shift everything over to make space. (Duplicating the
2087+
// `index`th element into two consecutive places.)
2088+
ptr::copy(p, p.add(1), len - index);
2089+
}
2090+
// Write it in, overwriting the first copy of the `index`th
2091+
// element.
2092+
ptr::write(p, element);
2093+
}
2094+
self.set_len(len + 1);
2095+
Some(&mut *p)
2096+
}
2097+
}
2098+
20392099
/// Removes and returns the element at position `index` within the vector,
20402100
/// shifting all elements after it to the left.
20412101
///

0 commit comments

Comments
 (0)