File tree Expand file tree Collapse file tree 2 files changed +50
-2
lines changed Expand file tree Collapse file tree 2 files changed +50
-2
lines changed Original file line number Diff line number Diff line change @@ -866,6 +866,18 @@ impl<T> VecDeque<T> {
866866 /// ```
867867 #[ stable( feature = "deque_extras" , since = "1.16.0" ) ]
868868 pub fn truncate ( & mut self , len : usize ) {
869+ /// Runs the destructor for all items in the slice when it gets dropped (normally or
870+ /// during unwinding).
871+ struct Dropper < ' a , T > ( & ' a mut [ T ] ) ;
872+
873+ impl < ' a , T > Drop for Dropper < ' a , T > {
874+ fn drop ( & mut self ) {
875+ unsafe {
876+ ptr:: drop_in_place ( self . 0 ) ;
877+ }
878+ }
879+ }
880+
869881 // Safe because:
870882 //
871883 // * Any slice passed to `drop_in_place` is valid; the second case has
@@ -888,8 +900,11 @@ impl<T> VecDeque<T> {
888900 let drop_back = back as * mut _ ;
889901 let drop_front = front. get_unchecked_mut ( len..) as * mut _ ;
890902 self . head = self . wrap_sub ( self . head , num_dropped) ;
903+
904+ // Make sure the second half is dropped even when a destructor
905+ // in the first one panics.
906+ let _back_dropper = Dropper ( & mut * drop_back) ;
891907 ptr:: drop_in_place ( drop_front) ;
892- ptr:: drop_in_place ( drop_back) ;
893908 }
894909 }
895910 }
Original file line number Diff line number Diff line change @@ -2,7 +2,7 @@ use std::collections::TryReserveError::*;
22use std:: collections:: { vec_deque:: Drain , VecDeque } ;
33use std:: fmt:: Debug ;
44use std:: mem:: size_of;
5- use std:: panic:: catch_unwind;
5+ use std:: panic:: { AssertUnwindSafe , catch_unwind} ;
66use std:: { isize, usize} ;
77
88use crate :: hash;
@@ -1573,3 +1573,36 @@ fn test_try_rfold_moves_iter() {
15731573 assert_eq ! ( iter. try_rfold( 0_i8 , |acc, & x| acc. checked_add( x) ) , None ) ;
15741574 assert_eq ! ( iter. next_back( ) , Some ( & 70 ) ) ;
15751575}
1576+
1577+ #[ test]
1578+ fn truncate_leak ( ) {
1579+ static mut DROPS : i32 = 0 ;
1580+
1581+ struct D ( bool ) ;
1582+
1583+ impl Drop for D {
1584+ fn drop ( & mut self ) {
1585+ unsafe {
1586+ DROPS += 1 ;
1587+ }
1588+
1589+ if self . 0 {
1590+ panic ! ( "panic in `drop`" ) ;
1591+ }
1592+ }
1593+ }
1594+
1595+ let mut q = VecDeque :: new ( ) ;
1596+ q. push_back ( D ( false ) ) ;
1597+ q. push_back ( D ( false ) ) ;
1598+ q. push_back ( D ( false ) ) ;
1599+ q. push_back ( D ( false ) ) ;
1600+ q. push_back ( D ( false ) ) ;
1601+ q. push_front ( D ( true ) ) ;
1602+ q. push_front ( D ( false ) ) ;
1603+ q. push_front ( D ( false ) ) ;
1604+
1605+ catch_unwind ( AssertUnwindSafe ( || q. truncate ( 1 ) ) ) . ok ( ) ;
1606+
1607+ assert_eq ! ( unsafe { DROPS } , 7 ) ;
1608+ }
You can’t perform that action at this time.
0 commit comments