diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index d03c1969b5b70..7d2bd094ccd40 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -844,11 +844,34 @@ impl LinkedList { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_front(&mut self, elt: T) { + let _ = self.push_front_mut(elt); + } + + /// Adds an element first in the list, returning a reference to it. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::from([1, 2, 3]); + /// + /// let ptr = dl.push_front_mut(2); + /// *ptr += 4; + /// assert_eq!(dl.front().unwrap(), &6); + /// ``` + #[unstable(feature = "push_mut", issue = "135974")] + #[must_use = "if you don't need a reference to the value, use LinkedList::push_front instead"] + pub fn push_front_mut(&mut self, elt: T) -> &mut T { let node = Box::new_in(Node::new(elt), &self.alloc); - let node_ptr = NonNull::from(Box::leak(node)); + let mut node_ptr = NonNull::from(Box::leak(node)); // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked unsafe { self.push_front_node(node_ptr); + &mut node_ptr.as_mut().element } } @@ -893,11 +916,34 @@ impl LinkedList { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_confusables("push", "append")] pub fn push_back(&mut self, elt: T) { + let _ = self.push_back_mut(elt); + } + + /// Adds an element last in the list, returning a reference to it. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::from([1, 2, 3]); + /// + /// let ptr = dl.push_back_mut(2); + /// *ptr += 4; + /// assert_eq!(dl.back().unwrap(), &6); + /// ``` + #[unstable(feature = "push_mut", issue = "135974")] + #[must_use = "if you don't need a reference to the value, use LinkedList::push_back instead"] + pub fn push_back_mut(&mut self, elt: T) -> &mut T { let node = Box::new_in(Node::new(elt), &self.alloc); - let node_ptr = NonNull::from(Box::leak(node)); + let mut node_ptr = NonNull::from(Box::leak(node)); // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked unsafe { self.push_back_node(node_ptr); + &mut node_ptr.as_mut().element } } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 08b1828ff000e..e699d8b4fd00d 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -182,11 +182,13 @@ impl VecDeque { unsafe { ptr::read(self.ptr().add(off)) } } - /// Writes an element into the buffer, moving it. + /// Writes an element into the buffer, moving it and returning a pointer to it. #[inline] - unsafe fn buffer_write(&mut self, off: usize, value: T) { + unsafe fn buffer_write(&mut self, off: usize, value: T) -> *mut T { unsafe { - ptr::write(self.ptr().add(off), value); + let ptr = self.ptr().add(off); + ptr::write(ptr, value); + ptr } } @@ -1920,10 +1922,66 @@ impl VecDeque { self.grow(); } - unsafe { self.buffer_write(self.to_physical_idx(self.len), value) } + unsafe { self.buffer_write(self.to_physical_idx(self.len), value) }; self.len += 1; } + /// Prepends an element to the deque, returning a reference to it. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::from([1, 2, 3]); + /// let x = d.push_front_mut(1); + /// *x -= 1; + /// assert_eq!(d.front(), Some(&0)); + /// ``` + #[unstable(feature = "push_mut", issue = "135974")] + #[track_caller] + #[must_use = "if you don't need a reference to the value, use VecDeque::push_front instead"] + pub fn push_front_mut(&mut self, value: T) -> &mut T { + if self.is_full() { + self.grow(); + } + + self.head = self.wrap_sub(self.head, 1); + self.len += 1; + + unsafe { + let ptr = self.buffer_write(self.head, value); + &mut *ptr + } + } + + /// Appends an element to the back of the deque, returning a reference to it. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::from([1, 2, 3]); + /// let x = d.push_back_mut(3); + /// *x += 1; + /// assert_eq!(d.back(), Some(&4)); + /// ``` + #[unstable(feature = "push_mut", issue = "135974")] + #[track_caller] + #[must_use = "if you don't need a reference to the value, use VecDeque::push_back instead"] + pub fn push_back_mut(&mut self, value: T) -> &mut T { + if self.is_full() { + self.grow(); + } + + let back_ptr = unsafe { self.buffer_write(self.to_physical_idx(self.len), value) }; + self.len += 1; + unsafe { &mut *back_ptr } + } + #[inline] fn is_contiguous(&self) -> bool { // Do the calculation like this to avoid overflowing if len + head > usize::MAX @@ -2056,6 +2114,64 @@ impl VecDeque { } } + /// Inserts an element at `index` within the deque, shifting all elements + /// with indices greater than or equal to `index` towards the back, + /// and returning a reference to it. + /// + /// Element at index 0 is the front of the queue. + /// + /// Returns [`None`] if `index` is strictly greater than deque's length. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// use std::collections::VecDeque; + /// + /// let mut vec_deque = VecDeque::from([1, 2, 3]); + /// + /// let x = vec_deque.insert_mut(1, 5).unwrap(); + /// *x += 7; + /// assert_eq!(vec_deque, &[1, 12, 2, 3]); + /// + /// let y = vec_deque.insert_mut(7, 5); + /// assert!(y.is_none()); + /// ``` + #[unstable(feature = "push_mut", issue = "135974")] + #[track_caller] + #[must_use = "if you don't need a reference to the value or type-safe bound checking, use VecDeque::insert instead"] + pub fn insert_mut(&mut self, index: usize, value: T) -> Option<&mut T> { + if index > self.len() { + return None; + } + if self.is_full() { + self.grow(); + } + + let k = self.len - index; + if k < index { + // `index + 1` can't overflow, because if index was usize::MAX, then either the + // assert would've failed, or the deque would've tried to grow past usize::MAX + // and panicked. + unsafe { + // see `remove()` for explanation why this wrap_copy() call is safe. + self.wrap_copy(self.to_physical_idx(index), self.to_physical_idx(index + 1), k); + let ptr = self.buffer_write(self.to_physical_idx(index), value); + self.len += 1; + Some(&mut *ptr) + } + } else { + let old_head = self.head; + self.head = self.wrap_sub(self.head, 1); + unsafe { + self.wrap_copy(old_head, self.head, index); + let ptr = self.buffer_write(self.to_physical_idx(index), value); + self.len += 1; + Some(&mut *ptr) + } + } + } + /// Removes and returns the element at `index` from the deque. /// Whichever end is closer to the removal point will be moved to make /// room, and all the affected elements will be moved to new positions. diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ce7321544b6b9..4070185c6e28c 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1974,6 +1974,8 @@ impl Vec { } } + + /// Inserts an element at position `index` within the vector, shifting all /// elements after it to the right. /// @@ -2036,6 +2038,64 @@ impl Vec { } } + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// Returns [`None`] if the specified index is out of bounds. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// let mut vec = vec![1, 3, 5, 9]; + /// let x = vec.insert_mut(3, 6).unwrap(); + /// *x += 1; + /// assert_eq!(vec, [1, 3, 5, 7, 9]); + /// + /// let y = vec.insert_mut(7, 6); + /// assert!(y.is_none()); + /// ``` + /// + /// # Time complexity + /// + /// Takes *O*([`Vec::len`]) time. All items after the insertion index must be + /// shifted to the right. In the worst case, all elements are shifted when + /// the insertion index is 0. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "push_mut", issue = "135974")] + #[track_caller] + #[must_use = "if you don't need a reference to the value or type-safe bound checking, use Vec::insert instead"] + pub fn insert_mut(&mut self, index: usize, element: T) -> Option<&mut T> { + let len = self.len(); + if index > len { + return None; + } + + // space for the new element + if len == self.buf.capacity() { + self.buf.grow_one(); + } + + unsafe { + // infallible + // The spot to put the new value + let p = self.as_mut_ptr().add(index); + { + if index < len { + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.add(1), len - index); + } + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + Some(&mut *p) + } + } + /// Removes and returns the element at position `index` within the vector, /// shifting all elements after it to the left. /// @@ -2503,6 +2563,104 @@ impl Vec { Ok(()) } + /// Appends an element to the back of a collection, returning a reference to it. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Examples + /// + /// ``` + /// #![feature(push_mut)] + /// + /// # #[allow(unused)] + /// #[derive(PartialEq, Eq, Debug)] + /// struct Item { identifier: &'static str, count: usize } + /// + /// impl Default for Item { + /// fn default() -> Self { + /// return Self { identifier: "stone", count: 64 } + /// } + /// } + /// + /// let mut items = vec![]; + /// + /// // We can mutate the just-pushed value without having to fetch it again + /// for count in [15, 35, 61] { + /// let item = items.push_mut(Item::default()); + /// item.count = count; + /// } + /// + /// assert_eq!( + /// items, + /// [Item { identifier: "stone", count: 15 }, Item { identifier: "stone", count: 35 }, Item { identifier: "stone", count: 61 }] + /// ); + /// ``` + /// + /// # Time complexity + /// + /// Takes amortized *O*(1) time. If the vector's length would exceed its + /// capacity after the push, *O*(*capacity*) time is taken to copy the + /// vector's elements to a larger allocation. This expensive operation is + /// offset by the *capacity* *O*(1) insertions it allows. + #[cfg(not(no_global_oom_handling))] + #[inline] + #[unstable(feature = "push_mut", issue = "135974")] + #[track_caller] + #[must_use = "if you don't need a reference to the value, use Vec::push instead"] + pub fn push_mut(&mut self, value: T) -> &mut T { + // Inform codegen that the length does not change across grow_one(). + let len = self.len; + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if len == self.buf.capacity() { + self.buf.grow_one(); + } + unsafe { + let end = self.as_mut_ptr().add(len); + ptr::write(end, value); + self.len = len + 1; + // SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference. + &mut *end + } + } + + /// Appends an element and returns a reference to it if there is sufficient spare capacity, otherwise an error is returned + /// with the element. + /// + /// Unlike [`push_mut`] this method will not reallocate when there's insufficient capacity. + /// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity. + /// + /// [`push_mut`]: Vec::push_mut + /// [`reserve`]: Vec::reserve + /// [`try_reserve`]: Vec::try_reserve + /// + /// # Time complexity + /// + /// Takes *O*(1) time. + // + // Since there's currently no way to have multiple unstable attributes on the same item, I compromised. + // Uncomment/delete the respective attribute when its respective issue stabilizes, since this falls under both. + // + #[unstable(feature = "push_mut", issue = "135974")] + // #[unstable(feature = "vec_push_within_capacity", issue = "100486")] + // + #[inline] + #[must_use = "if you don't need a reference to the value, use Vec::push_within_capacity instead"] + pub fn push_mut_within_capacity(&mut self, value: T) -> Result<&mut T, T> { + if self.len == self.buf.capacity() { + return Err(value); + } + unsafe { + let end = self.as_mut_ptr().add(self.len); + ptr::write(end, value); + self.len += 1; + // SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference. + Ok(&mut *end) + } + } + /// Removes the last element from a vector and returns it, or [`None`] if it /// is empty. /// diff --git a/src/tools/cargo b/src/tools/cargo index 64a12460708cf..68db37499f2de 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 64a12460708cf146e16cc61f28aba5dc2463bbb4 +Subproject commit 68db37499f2de8acef704c73d9031be6fbcbaee4