mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 18:27:37 +00:00
Rollup merge of #135975 - balt-dev:master, r=tgross35
Implement `push_mut` Implementation of rust-lang/rust#135974.
This commit is contained in:
commit
dc8aec4cf2
@ -825,7 +825,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
||||
unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().element) }
|
||||
}
|
||||
|
||||
/// Adds an element first in the list.
|
||||
/// Adds an element to the front of the list.
|
||||
///
|
||||
/// This operation should compute in *O*(1) time.
|
||||
///
|
||||
@ -844,11 +844,34 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn push_front(&mut self, elt: T) {
|
||||
let _ = self.push_front_mut(elt);
|
||||
}
|
||||
|
||||
/// Adds an element to the front of 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
|
||||
}
|
||||
}
|
||||
|
||||
@ -876,7 +899,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
||||
self.pop_front_node().map(Node::into_element)
|
||||
}
|
||||
|
||||
/// Appends an element to the back of a list.
|
||||
/// Adds an element to the back of the list.
|
||||
///
|
||||
/// This operation should compute in *O*(1) time.
|
||||
///
|
||||
@ -893,11 +916,34 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
||||
#[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 to the back of 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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,11 +182,16 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
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.
|
||||
/// # Safety
|
||||
///
|
||||
/// May only be called if `off < self.capacity()`.
|
||||
#[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);
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
@ -1888,16 +1893,34 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[track_caller]
|
||||
pub fn push_front(&mut self, value: T) {
|
||||
let _ = self.push_front_mut(value);
|
||||
}
|
||||
|
||||
/// 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(8);
|
||||
/// *x -= 1;
|
||||
/// assert_eq!(d.front(), Some(&7));
|
||||
/// ```
|
||||
#[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 {
|
||||
self.buffer_write(self.head, value);
|
||||
}
|
||||
// SAFETY: We know that self.head is within range of the deque.
|
||||
unsafe { self.buffer_write(self.head, value) }
|
||||
}
|
||||
|
||||
/// Appends an element to the back of the deque.
|
||||
@ -1916,12 +1939,33 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
#[rustc_confusables("push", "put", "append")]
|
||||
#[track_caller]
|
||||
pub fn push_back(&mut self, value: T) {
|
||||
let _ = self.push_back_mut(value);
|
||||
}
|
||||
|
||||
/// 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(9);
|
||||
/// *x += 1;
|
||||
/// assert_eq!(d.back(), Some(&10));
|
||||
/// ```
|
||||
#[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();
|
||||
}
|
||||
|
||||
unsafe { self.buffer_write(self.to_physical_idx(self.len), value) }
|
||||
let len = self.len;
|
||||
self.len += 1;
|
||||
unsafe { self.buffer_write(self.to_physical_idx(len), value) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -2007,7 +2051,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `index` is strictly greater than deque's length
|
||||
/// Panics if `index` is strictly greater than the deque's length.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2029,7 +2073,37 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
#[track_caller]
|
||||
pub fn insert(&mut self, index: usize, value: T) {
|
||||
let _ = self.insert_mut(index, value);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `index` is strictly greater than the 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);
|
||||
/// *x += 7;
|
||||
/// assert_eq!(vec_deque, &[1, 12, 2, 3]);
|
||||
/// ```
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[track_caller]
|
||||
#[must_use = "if you don't need a reference to the value, use `VecDeque::insert` instead"]
|
||||
pub fn insert_mut(&mut self, index: usize, value: T) -> &mut T {
|
||||
assert!(index <= self.len(), "index out of bounds");
|
||||
|
||||
if self.is_full() {
|
||||
self.grow();
|
||||
}
|
||||
@ -2042,16 +2116,16 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
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);
|
||||
self.buffer_write(self.to_physical_idx(index), value);
|
||||
self.len += 1;
|
||||
self.buffer_write(self.to_physical_idx(index), value)
|
||||
}
|
||||
} else {
|
||||
let old_head = self.head;
|
||||
self.head = self.wrap_sub(self.head, 1);
|
||||
unsafe {
|
||||
self.wrap_copy(old_head, self.head, index);
|
||||
self.buffer_write(self.to_physical_idx(index), value);
|
||||
self.len += 1;
|
||||
self.buffer_write(self.to_physical_idx(index), value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2046,6 +2046,38 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[track_caller]
|
||||
pub fn insert(&mut self, index: usize, element: T) {
|
||||
let _ = self.insert_mut(index, element);
|
||||
}
|
||||
|
||||
/// Inserts an element at position `index` within the vector, shifting all
|
||||
/// elements after it to the right, and returning a reference to the new
|
||||
/// element.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `index > len`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// let mut vec = vec![1, 3, 5, 9];
|
||||
/// let x = vec.insert_mut(3, 6);
|
||||
/// *x += 1;
|
||||
/// assert_eq!(vec, [1, 3, 5, 7, 9]);
|
||||
/// ```
|
||||
///
|
||||
/// # 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, use `Vec::insert` instead"]
|
||||
pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
|
||||
#[cold]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
@ -2067,8 +2099,8 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
unsafe {
|
||||
// infallible
|
||||
// The spot to put the new value
|
||||
let p = self.as_mut_ptr().add(index);
|
||||
{
|
||||
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.)
|
||||
@ -2079,6 +2111,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
ptr::write(p, element);
|
||||
}
|
||||
self.set_len(len + 1);
|
||||
&mut *p
|
||||
}
|
||||
}
|
||||
|
||||
@ -2486,18 +2519,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
#[rustc_confusables("push_back", "put", "append")]
|
||||
#[track_caller]
|
||||
pub fn push(&mut self, value: 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;
|
||||
}
|
||||
let _ = self.push_mut(value);
|
||||
}
|
||||
|
||||
/// Appends an element if there is sufficient spare capacity, otherwise an error is returned
|
||||
@ -2538,6 +2560,77 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
#[inline]
|
||||
#[unstable(feature = "vec_push_within_capacity", issue = "100486")]
|
||||
pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
|
||||
self.push_mut_within_capacity(value).map(|_| ())
|
||||
}
|
||||
|
||||
/// 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)]
|
||||
///
|
||||
///
|
||||
/// let mut vec = vec![1, 2];
|
||||
/// let last = vec.push_mut(3);
|
||||
/// assert_eq!(*last, 3);
|
||||
/// assert_eq!(vec, [1, 2, 3]);
|
||||
///
|
||||
/// let last = vec.push_mut(3);
|
||||
/// *last += 1;
|
||||
/// assert_eq!(vec, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
///
|
||||
/// # 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.
|
||||
#[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);
|
||||
}
|
||||
@ -2545,8 +2638,9 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
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)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes the last element from a vector and returns it, or [`None`] if it
|
||||
|
Loading…
x
Reference in New Issue
Block a user