@@ -2748,10 +2748,19 @@ pub struct DrainFilter<'a, T, F>
27482748 where F : FnMut ( & mut T ) -> bool ,
27492749{
27502750 vec : & ' a mut Vec < T > ,
2751+ /// The index of the item that will be inspected by the next call to `next`.
27512752 idx : usize ,
2753+ /// The number of items that have been drained (removed) thus far.
27522754 del : usize ,
2755+ /// The original length of `vec` prior to draining.
27532756 old_len : usize ,
2757+ /// The filter test predicate.
27542758 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.
27552764 panic_flag : bool ,
27562765}
27572766
@@ -2810,25 +2819,18 @@ impl<T, F> Drop for DrainFilter<'_, T, F>
28102819 {
28112820 fn drop ( & mut self ) {
28122821 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) ;
28322834 }
28332835 self . drain . vec . set_len ( self . drain . old_len - self . drain . del ) ;
28342836 }
0 commit comments