8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use std:: collections:: HashMap ;
12
+
11
13
use super :: universal_regions:: UniversalRegions ;
12
14
use rustc:: hir:: def_id:: DefId ;
13
15
use rustc:: infer:: InferCtxt ;
@@ -22,6 +24,7 @@ use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegi
22
24
use rustc:: traits:: ObligationCause ;
23
25
use rustc:: ty:: { self , RegionVid , Ty , TypeFoldable } ;
24
26
use rustc:: util:: common:: ErrorReported ;
27
+ use rustc_data_structures:: bitvec:: BitVector ;
25
28
use rustc_data_structures:: indexed_vec:: IndexVec ;
26
29
use rustc_errors:: DiagnosticBuilder ;
27
30
use std:: fmt;
@@ -452,8 +455,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
452
455
/// satisfied. Note that some values may grow **too** large to be
453
456
/// feasible, but we check this later.
454
457
fn propagate_constraints ( & mut self , mir : & Mir < ' tcx > ) {
455
- let mut changed = true ;
456
-
457
458
debug ! ( "propagate_constraints()" ) ;
458
459
debug ! ( "propagate_constraints: constraints={:#?}" , {
459
460
let mut constraints: Vec <_> = self . constraints. iter( ) . collect( ) ;
@@ -465,37 +466,60 @@ impl<'tcx> RegionInferenceContext<'tcx> {
465
466
// constraints we have accumulated.
466
467
let mut inferred_values = self . liveness_constraints . clone ( ) ;
467
468
468
- while changed {
469
- changed = false ;
470
- debug ! ( "propagate_constraints: --------------------" ) ;
471
- for constraint in & self . constraints {
472
- debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
473
-
474
- // Grow the value as needed to accommodate the
475
- // outlives constraint.
476
- let Ok ( made_changes) = self . dfs (
477
- mir,
478
- CopyFromSourceToTarget {
479
- source_region : constraint. sub ,
480
- target_region : constraint. sup ,
481
- inferred_values : & mut inferred_values,
482
- constraint_point : constraint. point ,
483
- constraint_span : constraint. span ,
484
- } ,
485
- ) ;
469
+ let dependency_map = self . build_dependency_map ( ) ;
470
+ let mut dirty_list: Vec < _ > = ( 0 ..self . constraints . len ( ) ) . collect ( ) ;
471
+ let mut dirty_bit_vec = BitVector :: new ( dirty_list. len ( ) ) ;
472
+
473
+ debug ! ( "propagate_constraints: --------------------" ) ;
474
+ while let Some ( constraint_idx) = dirty_list. pop ( ) {
475
+ dirty_bit_vec. remove ( constraint_idx) ;
476
+
477
+ let constraint = & self . constraints [ constraint_idx] ;
478
+ debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
479
+
480
+ // Grow the value as needed to accommodate the
481
+ // outlives constraint.
482
+ let Ok ( made_changes) = self . dfs (
483
+ mir,
484
+ CopyFromSourceToTarget {
485
+ source_region : constraint. sub ,
486
+ target_region : constraint. sup ,
487
+ inferred_values : & mut inferred_values,
488
+ constraint_point : constraint. point ,
489
+ constraint_span : constraint. span ,
490
+ } ,
491
+ ) ;
492
+
493
+ if made_changes {
494
+ debug ! ( "propagate_constraints: sub={:?}" , constraint. sub) ;
495
+ debug ! ( "propagate_constraints: sup={:?}" , constraint. sup) ;
486
496
487
- if made_changes {
488
- debug ! ( "propagate_constraints: sub={:?}" , constraint . sub ) ;
489
- debug ! ( "propagate_constraints: sup={:?}" , constraint . sup ) ;
490
- changed = true ;
497
+ for & dep_idx in dependency_map . get ( & constraint . sup ) . unwrap_or ( & vec ! [ ] ) {
498
+ if dirty_bit_vec . insert ( dep_idx ) {
499
+ dirty_list . push ( dep_idx ) ;
500
+ }
491
501
}
492
502
}
503
+
493
504
debug ! ( "\n " ) ;
494
505
}
495
506
496
507
self . inferred_values = Some ( inferred_values) ;
497
508
}
498
509
510
+ /// Builds up a map from each region variable X to a vector with the indices of constraints that
511
+ /// need to be re-evaluated when X changes. These are constraints like Y: X @ P -- so if X
512
+ /// changed, we may need to grow Y.
513
+ fn build_dependency_map ( & self ) -> HashMap < RegionVid , Vec < usize > > {
514
+ let mut map = HashMap :: new ( ) ;
515
+
516
+ for ( idx, constraint) in self . constraints . iter ( ) . enumerate ( ) {
517
+ map. entry ( constraint. sub ) . or_insert ( Vec :: new ( ) ) . push ( idx) ;
518
+ }
519
+
520
+ map
521
+ }
522
+
499
523
/// Once regions have been propagated, this method is used to see
500
524
/// whether the "type tests" produced by typeck were satisfied;
501
525
/// type tests encode type-outlives relationships like `T:
0 commit comments