diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index b20ccd388d1f1..f7d421ca0ccd4 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -1065,26 +1065,44 @@ impl Vec { fn assert_failed(index: usize, len: usize) -> ! { panic!("removal index (is {}) should be < len (is {})", index, len); } + if let Some(retval) = self.try_remove(index) { + retval + } else { + assert_failed(index, self.len()); + } + } + /// Tries to remove an element from the vector. If the element at `index` does not exist, + /// `None` is returned. Otherwise `Some(T)` is returned + /// + /// # 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 = "77481")] + pub fn try_remove(&mut self, index: usize) -> Option { let len = self.len(); if index >= len { - assert_failed(index, len); - } - unsafe { - // infallible - let ret; - { - // the place we are taking from. - let ptr = self.as_mut_ptr().add(index); - // copy it out, unsafely having a copy of the value on - // the stack and in the vector at the same time. - ret = ptr::read(ptr); - - // Shift everything down to fill in that spot. - ptr::copy(ptr.offset(1), ptr, len - index - 1); + None + } else { + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + // Shift everything down to fill in that spot. + ptr::copy(ptr.offset(1), ptr, len - index - 1); + } + self.set_len(len - 1); + Some(ret) } - self.set_len(len - 1); - ret } } diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index cff8ff9ac7ad9..4efeb0dc84c54 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -20,6 +20,7 @@ #![feature(inplace_iteration)] #![feature(iter_map_while)] #![feature(int_bits_const)] +#![feature(vec_try_remove)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index b7c7138db4f52..9d453fc32921e 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -518,6 +518,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 = vec![]; + assert!(v.try_remove(0).is_none()); +} + #[test] fn test_move_items() { let vec = vec![1, 2, 3];