Skip to content

Commit

Permalink
Restore original implementation of Vec::retain
Browse files Browse the repository at this point in the history
This PR reverts #48065, which aimed to optimize `Vec::retain` by
making use of `Vec::drain_filter`. Unfortunately at that time,
`drain_filter` was unsound.

The soundness hole in `Vec::drain_filter` was fixed in #61224 by
guaranteeing that cleanup logic runs via a nested `Drop`, even in
the event of a panic. Implementing this nested drop affects codegen
(apparently?) and results in slower code.

Fixes #65970
  • Loading branch information
aloucks committed Dec 14, 2019
1 parent 3964a55 commit 7ea6c46
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/liballoc/vec.rs
Expand Up @@ -1075,7 +1075,22 @@ impl<T> Vec<T> {
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&T) -> bool
{
self.drain_filter(|x| !f(x));
let len = self.len();
let mut del = 0;
{
let v = &mut **self;

for i in 0..len {
if !f(&v[i]) {
del += 1;
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del > 0 {
self.truncate(len - del);
}
}

/// Removes all but the first of consecutive elements in the vector that resolve to the same
Expand Down

0 comments on commit 7ea6c46

Please sign in to comment.