File tree Expand file tree Collapse file tree 2 files changed +21
-7
lines changed
library/alloc/src/collections/binary_heap Expand file tree Collapse file tree 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> {
851851 where
852852 F : FnMut ( & T ) -> bool ,
853853 {
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+
855861 let mut i = 0 ;
856- self . data . retain ( |e| {
862+ guard . heap . data . retain ( |e| {
857863 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;
860866 }
861867 i += 1 ;
862868 keep
863869 } ) ;
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+ }
866878 }
867879}
868880
Original file line number Diff line number Diff line change @@ -488,7 +488,9 @@ fn test_retain_catch_unwind() {
488488 } ) ;
489489 } ) ) ;
490490
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 ] ) ;
492494}
493495
494496// old binaryheap failed this test
You can’t perform that action at this time.
0 commit comments