@@ -1370,7 +1370,7 @@ impl<T, A: Allocator> Vec<T, A> {
13701370 where
13711371 F : FnMut ( & T ) -> bool ,
13721372 {
1373- let len = self . len ( ) ;
1373+ let original_len = self . len ( ) ;
13741374 // Avoid double drop if the drop guard is not executed,
13751375 // since we may make some holes during the process.
13761376 unsafe { self . set_len ( 0 ) } ;
@@ -1396,49 +1396,49 @@ impl<T, A: Allocator> Vec<T, A> {
13961396 impl < T , A : Allocator > Drop for BackshiftOnDrop < ' _ , T , A > {
13971397 fn drop ( & mut self ) {
13981398 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.
14001400 unsafe {
14011401 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 ) ,
14061404 self . original_len - self . processed_len ,
14071405 ) ;
1408- self . v . set_len ( self . original_len - self . deleted_cnt ) ;
14091406 }
14101407 }
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+ }
14111412 }
14121413 }
14131414
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 } ;
14161416
1417- let mut del = 0usize ;
1418- for i in 0 ..len {
1417+ while g. processed_len < original_len {
14191418 // 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 ) } ;
14211420 if !f ( cur) {
1422- del += 1 ;
14231421 // 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 ;
14261424 // SAFETY: We never touch this element again after dropped.
14271425 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.
14301431 // We use copy for move, and never touch this element again.
14311432 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 ) ;
14331434 ptr:: copy_nonoverlapping ( cur, hole_slot, 1 ) ;
14341435 }
1435- guard. processed_len = i + 1 ;
14361436 }
1437+ g. processed_len += 1 ;
14371438 }
14381439
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) ;
14421442 }
14431443
14441444 /// Removes all but the first of consecutive elements in the vector that resolve to the same
0 commit comments