@@ -2748,10 +2748,19 @@ pub struct DrainFilter<'a, T, F>
2748
2748
where F : FnMut ( & mut T ) -> bool ,
2749
2749
{
2750
2750
vec : & ' a mut Vec < T > ,
2751
+ /// The index of the item that will be inspected by the next call to `next`.
2751
2752
idx : usize ,
2753
+ /// The number of items that have been drained (removed) thus far.
2752
2754
del : usize ,
2755
+ /// The original length of `vec` prior to draining.
2753
2756
old_len : usize ,
2757
+ /// The filter test predicate.
2754
2758
pred : F ,
2759
+ /// A flag that indicates a panic has occured in the filter test prodicate.
2760
+ /// This is used as a hint in the drop implmentation to prevent consumption
2761
+ /// of the remainder of the `DrainFilter`. Any unprocessed items will be
2762
+ /// backshifted in the `vec`, but no further items will be dropped or
2763
+ /// tested by the filter predicate.
2755
2764
panic_flag : bool ,
2756
2765
}
2757
2766
@@ -2810,25 +2819,18 @@ impl<T, F> Drop for DrainFilter<'_, T, F>
2810
2819
{
2811
2820
fn drop ( & mut self ) {
2812
2821
unsafe {
2813
- // Backshift any unprocessed elements, preventing double-drop
2814
- // of any element that *should* have been previously overwritten
2815
- // but was not due to a panic in the filter predicate. This is
2816
- // implemented via drop so that it's guaranteed to run even in
2817
- // the event of a panic while consuming the remainder of the
2818
- // DrainFilter.
2819
- while self . drain . idx < self . drain . old_len {
2820
- let i = self . drain . idx ;
2821
- self . drain . idx += 1 ;
2822
- let v = slice:: from_raw_parts_mut (
2823
- self . drain . vec . as_mut_ptr ( ) ,
2824
- self . drain . old_len ,
2825
- ) ;
2826
- if self . drain . del > 0 {
2827
- let del = self . drain . del ;
2828
- let src: * const T = & v[ i] ;
2829
- let dst: * mut T = & mut v[ i - del] ;
2830
- ptr:: copy_nonoverlapping ( src, dst, 1 ) ;
2831
- }
2822
+ if self . drain . idx < self . drain . old_len && self . drain . del > 0 {
2823
+ // This is a pretty messed up state, and there isn't really an
2824
+ // obviously right thing to do. We don't want to keep trying
2825
+ // to execute `pred`, so we just backshift all the unprocessed
2826
+ // elements and tell the vec that they still exist. The backshift
2827
+ // is required to prevent a double-drop of the last successfully
2828
+ // drained item following a panic in the predicate.
2829
+ let ptr = self . drain . vec . as_mut_ptr ( ) ;
2830
+ let src = ptr. add ( self . drain . idx ) ;
2831
+ let dst = src. sub ( self . drain . del ) ;
2832
+ let tail_len = self . drain . old_len - self . drain . idx ;
2833
+ src. copy_to ( dst, tail_len) ;
2832
2834
}
2833
2835
self . drain . vec . set_len ( self . drain . old_len - self . drain . del ) ;
2834
2836
}
0 commit comments