Skip to content

Commit 7ea6c46

Browse files
committed
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
1 parent 3964a55 commit 7ea6c46

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/liballoc/vec.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,22 @@ impl<T> Vec<T> {
10751075
pub fn retain<F>(&mut self, mut f: F)
10761076
where F: FnMut(&T) -> bool
10771077
{
1078-
self.drain_filter(|x| !f(x));
1078+
let len = self.len();
1079+
let mut del = 0;
1080+
{
1081+
let v = &mut **self;
1082+
1083+
for i in 0..len {
1084+
if !f(&v[i]) {
1085+
del += 1;
1086+
} else if del > 0 {
1087+
v.swap(i - del, i);
1088+
}
1089+
}
1090+
}
1091+
if del > 0 {
1092+
self.truncate(len - del);
1093+
}
10791094
}
10801095

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

0 commit comments

Comments
 (0)