@@ -2700,23 +2700,40 @@ impl<T> DoubleEndedIterator for Drain<'_, T> {
27002700#[ stable( feature = "drain" , since = "1.6.0" ) ]
27012701impl < T > Drop for Drain < ' _ , T > {
27022702 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 > ) ;
27052705
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+ }
27162725 }
2717- source_vec. set_len ( start + self . tail_len ) ;
27182726 }
27192727 }
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 ) ;
27202737 }
27212738}
27222739
0 commit comments