File tree 2 files changed +21
-7
lines changed
library/alloc/src/collections/binary_heap
2 files changed +21
-7
lines changed Original file line number Diff line number Diff line change @@ -851,18 +851,30 @@ impl<T: Ord> BinaryHeap<T> {
851
851
where
852
852
F : FnMut ( & T ) -> bool ,
853
853
{
854
- let mut first_removed = self . len ( ) ;
854
+ struct RebuildOnDrop < ' a , T : Ord > {
855
+ heap : & ' a mut BinaryHeap < T > ,
856
+ first_removed : usize ,
857
+ }
858
+
859
+ let mut guard = RebuildOnDrop { first_removed : self . len ( ) , heap : self } ;
860
+
855
861
let mut i = 0 ;
856
- self . data . retain ( |e| {
862
+ guard . heap . data . retain ( |e| {
857
863
let keep = f ( e) ;
858
- if !keep && i < first_removed {
859
- first_removed = i;
864
+ if !keep && i < guard . first_removed {
865
+ guard . first_removed = i;
860
866
}
861
867
i += 1 ;
862
868
keep
863
869
} ) ;
864
- // data[0..first_removed] is untouched, so we only need to rebuild the tail:
865
- self . rebuild_tail ( first_removed) ;
870
+
871
+ impl < ' a , T : Ord > Drop for RebuildOnDrop < ' a , T > {
872
+ fn drop ( & mut self ) {
873
+ // data[..first_removed] is untouched, so we only need to
874
+ // rebuild the tail:
875
+ self . heap . rebuild_tail ( self . first_removed ) ;
876
+ }
877
+ }
866
878
}
867
879
}
868
880
Original file line number Diff line number Diff line change @@ -488,7 +488,9 @@ fn test_retain_catch_unwind() {
488
488
} ) ;
489
489
} ) ) ;
490
490
491
- assert_eq ! ( heap. into_vec( ) , [ 1 , 2 ] ) ; // BAD!!
491
+ // Naively this would be [1, 2] (an invalid heap) if BinaryHeap delegates to
492
+ // Vec's retain impl and then does not rebuild the heap after that unwinds.
493
+ assert_eq ! ( heap. into_vec( ) , [ 2 , 1 ] ) ;
492
494
}
493
495
494
496
// old binaryheap failed this test
You can’t perform that action at this time.
0 commit comments