about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-09-25 18:15:09 +0200
committerGitHub <noreply@github.com>2025-09-25 18:15:09 +0200
commitfea9196e5271a61dc526246a6ccdc2db0f998603 (patch)
tree49118852543474c42710fb3a27c1483a280473d8
parent958d1438b6916ade1b89d8527c898254159685c3 (diff)
parent56734495e2fd485a7be1ba77da1bf18a0eca4636 (diff)
downloadrust-fea9196e5271a61dc526246a6ccdc2db0f998603.tar.gz
rust-fea9196e5271a61dc526246a6ccdc2db0f998603.zip
Rollup merge of #146293 - BenjaminBrienen:try_remove, r=joboet
feat: non-panicking `Vec::try_remove`

`if index < my_vector.len() { Some(my_vector.remove(index)) } else { None }` is annoying to write and non-panicking functions are broadly useful.

APC: https://github.com/rust-lang/libs-team/issues/649

Tracking issue: https://github.com/rust-lang/rust/issues/146954
-rw-r--r--library/alloc/src/vec/mod.rs32
-rw-r--r--library/alloctests/tests/lib.rs1
-rw-r--r--library/alloctests/tests/vec.rs15
3 files changed, 46 insertions, 2 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index ebdb86f98a8..694b7b2df08 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -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)
         }
     }
 
diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs
index 8c3ce156f3c..cba9883e148 100644
--- a/library/alloctests/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -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)]
diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs
index 33a34daccbf..ea334ab0f14 100644
--- a/library/alloctests/tests/vec.rs
+++ b/library/alloctests/tests/vec.rs
@@ -631,6 +631,21 @@ fn test_swap_remove_empty() {
 }
 
 #[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];
     let mut vec2 = vec![];