Rollup merge of #67300 - aloucks:issue-65970, r=rkruppe

Restore original implementation of Vec::retain

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
This commit is contained in:
Mazdak Farrokhzad 2019-12-15 05:57:27 +01:00 committed by GitHub
commit 64f83915de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1079,7 +1079,22 @@ impl<T> Vec<T> {
pub fn retain<F>(&mut self, mut f: F) pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&T) -> bool 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 /// Removes all but the first of consecutive elements in the vector that resolve to the same