diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-03-27 05:21:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-27 05:21:18 +0100 |
| commit | 19a40ec5bf41d4bf5a8635be511ac9cb84308f25 (patch) | |
| tree | f17426859245d97e33698d2ee87cb979ca0470fe | |
| parent | fc51dbd379ec80000343fa03315a113b2389c454 (diff) | |
| parent | 07d3806eb1a9dcfc6acdc54476c9cc2b7bbbad7b (diff) | |
| download | rust-19a40ec5bf41d4bf5a8635be511ac9cb84308f25.tar.gz rust-19a40ec5bf41d4bf5a8635be511ac9cb84308f25.zip | |
Rollup merge of #123107 - avandesa:vec_pop_if, r=joboet
Implement `Vec::pop_if`
This PR adds `Vec::pop_if` to the public API, behind the `vec_pop_if` feature.
```rust
impl<T> Vec<T> {
pub fn pop_if<F>(&mut self, f: F) -> Option<T>
where F: FnOnce(&mut T) -> bool;
}
```
Tracking issue: #122741
## Open questions
- [ ] Should the first unit test be split up?
- [ ] I don't see any guidance on ordering of methods in impl blocks, should I move the method elsewhere?
| -rw-r--r-- | library/alloc/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 25 | ||||
| -rw-r--r-- | library/alloc/tests/lib.rs | 1 | ||||
| -rw-r--r-- | library/alloc/tests/vec.rs | 30 |
4 files changed, 57 insertions, 0 deletions
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ebc30c08910..20b7d0afa87 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -170,6 +170,7 @@ #![feature(unicode_internals)] #![feature(unsize)] #![feature(utf8_chunks)] +#![feature(vec_pop_if)] // tidy-alphabetical-end // // Language features: diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3062f8664b7..8ca8046dac5 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2058,6 +2058,31 @@ impl<T, A: Allocator> Vec<T, A> { } } + /// Removes and returns the last element in a vector if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the vector + /// is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_pop_if)] + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// let pred = |x: &mut i32| *x % 2 == 0; + /// + /// assert_eq!(vec.pop_if(pred), Some(4)); + /// assert_eq!(vec, [1, 2, 3]); + /// assert_eq!(vec.pop_if(pred), None); + /// ``` + #[unstable(feature = "vec_pop_if", issue = "122741")] + pub fn pop_if<F>(&mut self, f: F) -> Option<T> + where + F: FnOnce(&mut T) -> bool, + { + let last = self.last_mut()?; + if f(last) { self.pop() } else { None } + } + /// Moves all the elements of `other` into `self`, leaving `other` empty. /// /// # Panics diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f58998fbd79..04709af5c0a 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -43,6 +43,7 @@ #![feature(strict_provenance)] #![feature(drain_keep_rest)] #![feature(local_waker)] +#![feature(vec_pop_if)] #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index f1f841fe190..71d79893e01 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2644,6 +2644,36 @@ fn test_vec_from_array_mut_ref() { assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); } +#[test] +fn test_pop_if() { + let mut v = vec![1, 2, 3, 4]; + let pred = |x: &mut i32| *x % 2 == 0; + + assert_eq!(v.pop_if(pred), Some(4)); + assert_eq!(v, [1, 2, 3]); + + assert_eq!(v.pop_if(pred), None); + assert_eq!(v, [1, 2, 3]); +} + +#[test] +fn test_pop_if_empty() { + let mut v = Vec::<i32>::new(); + assert_eq!(v.pop_if(|_| true), None); + assert!(v.is_empty()); +} + +#[test] +fn test_pop_if_mutates() { + let mut v = vec![1]; + let pred = |x: &mut i32| { + *x += 1; + false + }; + assert_eq!(v.pop_if(pred), None); + assert_eq!(v, [2]); +} + /// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments /// in the stdlib. Draining and extending the allocation are fairly well-tested earlier, but /// `vec.insert(usize::MAX, val)` once slipped by! |
