Skip to content

Commit f41202a

Browse files
authored
Unrolled build for #146293
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: rust-lang/libs-team#649 Tracking issue: #146954
2 parents eabf390 + 5673449 commit f41202a

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

library/alloc/src/vec/mod.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,9 +2173,37 @@ impl<T, A: Allocator> Vec<T, A> {
21732173
panic!("removal index (is {index}) should be < len (is {len})");
21742174
}
21752175

2176+
match self.try_remove(index) {
2177+
Some(elem) => elem,
2178+
None => assert_failed(index, self.len()),
2179+
}
2180+
}
2181+
2182+
/// Remove and return the element at position `index` within the vector,
2183+
/// shifting all elements after it to the left, or [`None`] if it does not
2184+
/// exist.
2185+
///
2186+
/// Note: Because this shifts over the remaining elements, it has a
2187+
/// worst-case performance of *O*(*n*). If you'd like to remove
2188+
/// elements from the beginning of the `Vec`, consider using
2189+
/// [`VecDeque::pop_front`] instead.
2190+
///
2191+
/// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front
2192+
///
2193+
/// # Examples
2194+
///
2195+
/// ```
2196+
/// #![feature(vec_try_remove)]
2197+
/// let mut v = vec![1, 2, 3];
2198+
/// assert_eq!(v.try_remove(0), Some(1));
2199+
/// assert_eq!(v.try_remove(2), None);
2200+
/// ```
2201+
#[unstable(feature = "vec_try_remove", issue = "146954")]
2202+
#[rustc_confusables("delete", "take", "remove")]
2203+
pub fn try_remove(&mut self, index: usize) -> Option<T> {
21762204
let len = self.len();
21772205
if index >= len {
2178-
assert_failed(index, len);
2206+
return None;
21792207
}
21802208
unsafe {
21812209
// infallible
@@ -2191,7 +2219,7 @@ impl<T, A: Allocator> Vec<T, A> {
21912219
ptr::copy(ptr.add(1), ptr, len - index - 1);
21922220
}
21932221
self.set_len(len - 1);
2194-
ret
2222+
Some(ret)
21952223
}
21962224
}
21972225

library/alloctests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#![feature(unique_rc_arc)]
4242
#![feature(macro_metavar_expr_concat)]
4343
#![feature(vec_peek_mut)]
44+
#![feature(vec_try_remove)]
4445
#![allow(internal_features)]
4546
#![deny(fuzzy_provenance_casts)]
4647
#![deny(unsafe_op_in_unsafe_fn)]

library/alloctests/tests/vec.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,21 @@ fn test_swap_remove_empty() {
630630
vec.swap_remove(0);
631631
}
632632

633+
#[test]
634+
fn test_try_remove() {
635+
let mut vec = vec![1, 2, 3];
636+
// We are attempting to remove vec[0] which contains 1
637+
assert_eq!(vec.try_remove(0), Some(1));
638+
// Now `vec` looks like: [2, 3]
639+
// We will now try to remove vec[2] which does not exist
640+
// This should return `None`
641+
assert_eq!(vec.try_remove(2), None);
642+
643+
// We will try the same thing with an empty vector
644+
let mut v: Vec<u8> = vec![];
645+
assert!(v.try_remove(0).is_none());
646+
}
647+
633648
#[test]
634649
fn test_move_items() {
635650
let vec = vec![1, 2, 3];

0 commit comments

Comments
 (0)