@@ -1370,7 +1370,7 @@ impl<T, A: Allocator> Vec<T, A> {
1370
1370
where
1371
1371
F : FnMut ( & T ) -> bool ,
1372
1372
{
1373
- let len = self . len ( ) ;
1373
+ let original_len = self . len ( ) ;
1374
1374
// Avoid double drop if the drop guard is not executed,
1375
1375
// since we may make some holes during the process.
1376
1376
unsafe { self . set_len ( 0 ) } ;
@@ -1396,49 +1396,49 @@ impl<T, A: Allocator> Vec<T, A> {
1396
1396
impl < T , A : Allocator > Drop for BackshiftOnDrop < ' _ , T , A > {
1397
1397
fn drop ( & mut self ) {
1398
1398
if self . deleted_cnt > 0 {
1399
- // SAFETY: Fill the hole of dropped or moved
1399
+ // SAFETY: Trailing unchecked items must be valid since we never touch them.
1400
1400
unsafe {
1401
1401
ptr:: copy (
1402
- self . v . as_ptr ( ) . offset ( self . processed_len as isize ) ,
1403
- self . v
1404
- . as_mut_ptr ( )
1405
- . offset ( self . processed_len as isize - self . deleted_cnt as isize ) ,
1402
+ self . v . as_ptr ( ) . add ( self . processed_len ) ,
1403
+ self . v . as_mut_ptr ( ) . add ( self . processed_len - self . deleted_cnt ) ,
1406
1404
self . original_len - self . processed_len ,
1407
1405
) ;
1408
- self . v . set_len ( self . original_len - self . deleted_cnt ) ;
1409
1406
}
1410
1407
}
1408
+ // SAFETY: After filling holes, all items are in contiguous memory.
1409
+ unsafe {
1410
+ self . v . set_len ( self . original_len - self . deleted_cnt ) ;
1411
+ }
1411
1412
}
1412
1413
}
1413
1414
1414
- let mut guard =
1415
- BackshiftOnDrop { v : self , processed_len : 0 , deleted_cnt : 0 , original_len : len } ;
1415
+ let mut g = BackshiftOnDrop { v : self , processed_len : 0 , deleted_cnt : 0 , original_len } ;
1416
1416
1417
- let mut del = 0usize ;
1418
- for i in 0 ..len {
1417
+ while g. processed_len < original_len {
1419
1418
// SAFETY: Unchecked element must be valid.
1420
- let cur = unsafe { & mut * guard . v . as_mut_ptr ( ) . offset ( i as isize ) } ;
1419
+ let cur = unsafe { & mut * g . v . as_mut_ptr ( ) . add ( g . processed_len ) } ;
1421
1420
if !f ( cur) {
1422
- del += 1 ;
1423
1421
// Advance early to avoid double drop if `drop_in_place` panicked.
1424
- guard . processed_len = i + 1 ;
1425
- guard . deleted_cnt = del ;
1422
+ g . processed_len += 1 ;
1423
+ g . deleted_cnt += 1 ;
1426
1424
// SAFETY: We never touch this element again after dropped.
1427
1425
unsafe { ptr:: drop_in_place ( cur) } ;
1428
- } else if del > 0 {
1429
- // SAFETY: `del` > 0 so the hole slot must not overlap with current element.
1426
+ // We already advanced the counter.
1427
+ continue ;
1428
+ }
1429
+ if g. deleted_cnt > 0 {
1430
+ // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element.
1430
1431
// We use copy for move, and never touch this element again.
1431
1432
unsafe {
1432
- let hole_slot = guard . v . as_mut_ptr ( ) . offset ( i as isize - del as isize ) ;
1433
+ let hole_slot = g . v . as_mut_ptr ( ) . add ( g . processed_len - g . deleted_cnt ) ;
1433
1434
ptr:: copy_nonoverlapping ( cur, hole_slot, 1 ) ;
1434
1435
}
1435
- guard. processed_len = i + 1 ;
1436
1436
}
1437
+ g. processed_len += 1 ;
1437
1438
}
1438
1439
1439
- // All holes are at the end now. Simply cut them out.
1440
- unsafe { guard. v . set_len ( len - del) } ;
1441
- mem:: forget ( guard) ;
1440
+ // All item are processed. This can be optimized to `set_len` by LLVM.
1441
+ drop ( g) ;
1442
1442
}
1443
1443
1444
1444
/// Removes all but the first of consecutive elements in the vector that resolve to the same
0 commit comments