@@ -304,8 +304,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
304
304
}
305
305
306
306
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>| {
309
308
let (a_region, b_vid, b_data, retain) = match *constraint {
310
309
Constraint::RegSubVar(a_region, b_vid) => {
311
310
let b_data = var_values.value_mut(b_vid);
@@ -331,7 +330,33 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
331
330
332
331
let changed = self.expand_node(a_region, b_vid, b_data);
333
332
(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
+ }
335
360
}
336
361
337
362
// This function is very hot in some workloads. There's a single callsite
@@ -866,42 +891,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
866
891
}
867
892
}
868
893
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
-
905
894
fn bound_is_met(
906
895
&self,
907
896
bound: &VerifyBound<'tcx>,
0 commit comments