This repository was archived by the owner on May 28, 2025. It is now read-only.
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> {
866
866
/// ```
867
867
#[ stable( feature = "deque_extras" , since = "1.16.0" ) ]
868
868
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
+
869
881
// Safe because:
870
882
//
871
883
// * Any slice passed to `drop_in_place` is valid; the second case has
@@ -888,8 +900,11 @@ impl<T> VecDeque<T> {
888
900
let drop_back = back as * mut _ ;
889
901
let drop_front = front. get_unchecked_mut ( len..) as * mut _ ;
890
902
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) ;
891
907
ptr:: drop_in_place ( drop_front) ;
892
- ptr:: drop_in_place ( drop_back) ;
893
908
}
894
909
}
895
910
}
Original file line number Diff line number Diff line change @@ -2,7 +2,7 @@ use std::collections::TryReserveError::*;
2
2
use std:: collections:: { vec_deque:: Drain , VecDeque } ;
3
3
use std:: fmt:: Debug ;
4
4
use std:: mem:: size_of;
5
- use std:: panic:: catch_unwind;
5
+ use std:: panic:: { AssertUnwindSafe , catch_unwind} ;
6
6
use std:: { isize, usize} ;
7
7
8
8
use crate :: hash;
@@ -1573,3 +1573,36 @@ fn test_try_rfold_moves_iter() {
1573
1573
assert_eq ! ( iter. try_rfold( 0_i8 , |acc, & x| acc. checked_add( x) ) , None ) ;
1574
1574
assert_eq ! ( iter. next_back( ) , Some ( & 70 ) ) ;
1575
1575
}
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