@@ -304,8 +304,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
304304 }
305305
306306 fn expansion ( & self , var_values : & mut LexicalRegionResolutions < ' tcx > ) {
307- self . iterate_until_fixed_point ( |constraint| {
308- debug ! ( "expansion: constraint={:?}" , constraint) ;
307+ let mut process_constraint = |constraint : & Constraint < ' tcx > | {
309308 let ( a_region, b_vid, b_data, retain) = match * constraint {
310309 Constraint :: RegSubVar ( a_region, b_vid) => {
311310 let b_data = var_values. value_mut ( b_vid) ;
@@ -331,7 +330,33 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
331330
332331 let changed = self . expand_node ( a_region, b_vid, b_data) ;
333332 ( changed, retain)
334- } )
333+ } ;
334+
335+ // Using bitsets to track the remaining elements is faster than using a
336+ // `Vec` by itself (which requires removing elements, which requires
337+ // element shuffling, which is slow).
338+ let constraints: Vec < _ > = self . data . constraints . keys ( ) . collect ( ) ;
339+ let mut live_indices: BitSet < usize > = BitSet :: new_filled ( constraints. len ( ) ) ;
340+ let mut killed_indices: BitSet < usize > = BitSet :: new_empty ( constraints. len ( ) ) ;
341+ let mut changed = true ;
342+ while changed {
343+ changed = false ;
344+ for index in live_indices. iter ( ) {
345+ let constraint = constraints[ index] ;
346+ let ( edge_changed, retain) = process_constraint ( constraint) ;
347+ if edge_changed {
348+ changed = true ;
349+ }
350+ if !retain {
351+ let changed = killed_indices. insert ( index) ;
352+ debug_assert ! ( changed) ;
353+ }
354+ }
355+ live_indices. subtract ( & killed_indices) ;
356+
357+ // We could clear `killed_indices` here, but we don't need to and
358+ // it's cheaper not to.
359+ }
335360 }
336361
337362 // This function is very hot in some workloads. There's a single callsite
@@ -866,42 +891,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
866891 }
867892 }
868893
869- fn iterate_until_fixed_point < F > ( & self , mut body : F )
870- where
871- F : FnMut ( & Constraint < ' tcx > ) -> ( bool , bool ) ,
872- {
873- // Using bitsets to track the remaining elements is faster than using a
874- // `Vec` by itself (which requires removing elements, which requires
875- // element shuffling, which is slow).
876- let constraints: Vec < _ > = self . data . constraints . keys ( ) . collect ( ) ;
877- let mut live_indices: BitSet < usize > = BitSet :: new_filled ( constraints. len ( ) ) ;
878- let mut killed_indices: BitSet < usize > = BitSet :: new_empty ( constraints. len ( ) ) ;
879- let mut iteration = 0 ;
880- let mut changed = true ;
881- while changed {
882- changed = false ;
883- iteration += 1 ;
884- debug ! ( "---- Expansion iteration {}" , iteration) ;
885- for index in live_indices. iter ( ) {
886- let constraint = constraints[ index] ;
887- let ( edge_changed, retain) = body ( constraint) ;
888- if edge_changed {
889- debug ! ( "updated due to constraint {:?}" , constraint) ;
890- changed = true ;
891- }
892- if !retain {
893- let changed = killed_indices. insert ( index) ;
894- debug_assert ! ( changed) ;
895- }
896- }
897- live_indices. subtract ( & killed_indices) ;
898-
899- // We could clear `killed_indices` here, but we don't need to and
900- // it's cheaper not to.
901- }
902- debug ! ( "---- Expansion complete after {} iteration(s)" , iteration) ;
903- }
904-
905894 fn bound_is_met (
906895 & self ,
907896 bound : & VerifyBound < ' tcx > ,
0 commit comments