feature: Implement vec_try_remove

Vec::try_remove is a non-panicking version of Vec::remove
This commit is contained in:
BenjaminBrienen 2025-09-24 14:25:10 +02:00
parent 3e887f5faa
commit 56734495e2
3 changed files with 46 additions and 2 deletions

View File

@ -2173,9 +2173,37 @@ impl<T, A: Allocator> Vec<T, A> {
panic!("removal index (is {index}) should be < len (is {len})");
}
match self.try_remove(index) {
Some(elem) => elem,
None => assert_failed(index, self.len()),
}
}
/// Remove and return the element at position `index` within the vector,
/// shifting all elements after it to the left, or [`None`] if it does not
/// exist.
///
/// Note: Because this shifts over the remaining elements, it has a
/// worst-case performance of *O*(*n*). If you'd like to remove
/// elements from the beginning of the `Vec`, consider using
/// [`VecDeque::pop_front`] instead.
///
/// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front
///
/// # Examples
///
/// ```
/// #![feature(vec_try_remove)]
/// let mut v = vec![1, 2, 3];
/// assert_eq!(v.try_remove(0), Some(1));
/// assert_eq!(v.try_remove(2), None);
/// ```
#[unstable(feature = "vec_try_remove", issue = "146954")]
#[rustc_confusables("delete", "take", "remove")]
pub fn try_remove(&mut self, index: usize) -> Option<T> {
let len = self.len();
if index >= len {
assert_failed(index, len);
return None;
}
unsafe {
// infallible
@ -2191,7 +2219,7 @@ impl<T, A: Allocator> Vec<T, A> {
ptr::copy(ptr.add(1), ptr, len - index - 1);
}
self.set_len(len - 1);
ret
Some(ret)
}
}

View File

@ -41,6 +41,7 @@
#![feature(unique_rc_arc)]
#![feature(macro_metavar_expr_concat)]
#![feature(vec_peek_mut)]
#![feature(vec_try_remove)]
#![allow(internal_features)]
#![deny(fuzzy_provenance_casts)]
#![deny(unsafe_op_in_unsafe_fn)]

View File

@ -630,6 +630,21 @@ fn test_swap_remove_empty() {
vec.swap_remove(0);
}
#[test]
fn test_try_remove() {
let mut vec = vec![1, 2, 3];
// We are attempting to remove vec[0] which contains 1
assert_eq!(vec.try_remove(0), Some(1));
// Now `vec` looks like: [2, 3]
// We will now try to remove vec[2] which does not exist
// This should return `None`
assert_eq!(vec.try_remove(2), None);
// We will try the same thing with an empty vector
let mut v: Vec<u8> = vec![];
assert!(v.try_remove(0).is_none());
}
#[test]
fn test_move_items() {
let vec = vec![1, 2, 3];