Optimize unnecessary check in Vec::retain
Co-authored-by: oxalica <oxalicc@pm.me>
This commit is contained in:
parent
20e14e4030
commit
3839ca9953
@ -1485,7 +1485,15 @@ fn drop(&mut self) {
|
||||
|
||||
let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len };
|
||||
|
||||
while g.processed_len < original_len {
|
||||
// process_one return a bool indicates whether the processing element should be retained.
|
||||
#[inline(always)]
|
||||
fn process_one<F, T, A: Allocator, const DELETED: bool>(
|
||||
f: &mut F,
|
||||
g: &mut BackshiftOnDrop<'_, T, A>,
|
||||
) -> bool
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
// SAFETY: Unchecked element must be valid.
|
||||
let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) };
|
||||
if !f(cur) {
|
||||
@ -1495,9 +1503,9 @@ fn drop(&mut self) {
|
||||
// SAFETY: We never touch this element again after dropped.
|
||||
unsafe { ptr::drop_in_place(cur) };
|
||||
// We already advanced the counter.
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
if g.deleted_cnt > 0 {
|
||||
if DELETED {
|
||||
// SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element.
|
||||
// We use copy for move, and never touch this element again.
|
||||
unsafe {
|
||||
@ -1506,6 +1514,19 @@ fn drop(&mut self) {
|
||||
}
|
||||
}
|
||||
g.processed_len += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stage 1: Nothing was deleted.
|
||||
while g.processed_len != original_len {
|
||||
if !process_one::<F, T, A, false>(&mut f, &mut g) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 2: Some elements were deleted.
|
||||
while g.processed_len != original_len {
|
||||
process_one::<F, T, A, true>(&mut f, &mut g);
|
||||
}
|
||||
|
||||
// All item are processed. This can be optimized to `set_len` by LLVM.
|
||||
|
Loading…
Reference in New Issue
Block a user