@@ -2700,23 +2700,40 @@ impl<T> DoubleEndedIterator for Drain<'_, T> {
2700
2700
#[ stable( feature = "drain" , since = "1.6.0" ) ]
2701
2701
impl < T > Drop for Drain < ' _ , T > {
2702
2702
fn drop ( & mut self ) {
2703
- // exhaust self first
2704
- self . for_each ( drop ) ;
2703
+ /// Continues dropping the remaining elements when a destructor unwinds.
2704
+ struct DropGuard < ' r , ' a , T > ( & ' r mut Drain < ' a , T > ) ;
2705
2705
2706
- if self . tail_len > 0 {
2707
- unsafe {
2708
- let source_vec = self . vec . as_mut ( ) ;
2709
- // memmove back untouched tail, update to new length
2710
- let start = source_vec. len ( ) ;
2711
- let tail = self . tail_start ;
2712
- if tail != start {
2713
- let src = source_vec. as_ptr ( ) . add ( tail) ;
2714
- let dst = source_vec. as_mut_ptr ( ) . add ( start) ;
2715
- ptr:: copy ( src, dst, self . tail_len ) ;
2706
+ impl < ' r , ' a , T > Drop for DropGuard < ' r , ' a , T > {
2707
+ fn drop ( & mut self ) {
2708
+ // Continue the same loop we do below. This only runs when a destructor has
2709
+ // panicked. If another one panics this will abort.
2710
+ self . 0 . for_each ( drop) ;
2711
+
2712
+ if self . 0 . tail_len > 0 {
2713
+ unsafe {
2714
+ let source_vec = self . 0 . vec . as_mut ( ) ;
2715
+ // memmove back untouched tail, update to new length
2716
+ let start = source_vec. len ( ) ;
2717
+ let tail = self . 0 . tail_start ;
2718
+ if tail != start {
2719
+ let src = source_vec. as_ptr ( ) . add ( tail) ;
2720
+ let dst = source_vec. as_mut_ptr ( ) . add ( start) ;
2721
+ ptr:: copy ( src, dst, self . 0 . tail_len ) ;
2722
+ }
2723
+ source_vec. set_len ( start + self . 0 . tail_len ) ;
2724
+ }
2716
2725
}
2717
- source_vec. set_len ( start + self . tail_len ) ;
2718
2726
}
2719
2727
}
2728
+
2729
+ // exhaust self first
2730
+ while let Some ( item) = self . next ( ) {
2731
+ let guard = DropGuard ( self ) ;
2732
+ drop ( item) ;
2733
+ mem:: forget ( guard) ;
2734
+ }
2735
+
2736
+ DropGuard ( self ) ;
2720
2737
}
2721
2738
}
2722
2739
0 commit comments