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,65 @@ 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
+
471
+ // Constraints that may need to be repropagated (initially all):
472
+ let mut dirty_list: Vec < _ > = ( 0 ..self . constraints . len ( ) ) . collect ( ) ;
473
+
474
+ // Set to 0 for each constraint that is on the dirty list:
475
+ let mut clean_bit_vec = BitVector :: new ( dirty_list. len ( ) ) ;
476
+
477
+ debug ! ( "propagate_constraints: --------------------" ) ;
478
+ while let Some ( constraint_idx) = dirty_list. pop ( ) {
479
+ clean_bit_vec. insert ( constraint_idx) ;
480
+
481
+ let constraint = & self . constraints [ constraint_idx] ;
482
+ debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
486
483
487
- if made_changes {
488
- debug ! ( "propagate_constraints: sub={:?}" , constraint. sub) ;
489
- debug ! ( "propagate_constraints: sup={:?}" , constraint. sup) ;
490
- changed = true ;
484
+ // Grow the value as needed to accommodate the
485
+ // outlives constraint.
486
+ let Ok ( made_changes) = self . dfs (
487
+ mir,
488
+ CopyFromSourceToTarget {
489
+ source_region : constraint. sub ,
490
+ target_region : constraint. sup ,
491
+ inferred_values : & mut inferred_values,
492
+ constraint_point : constraint. point ,
493
+ constraint_span : constraint. span ,
494
+ } ,
495
+ ) ;
496
+
497
+ if made_changes {
498
+ debug ! ( "propagate_constraints: sub={:?}" , constraint. sub) ;
499
+ debug ! ( "propagate_constraints: sup={:?}" , constraint. sup) ;
500
+
501
+ for & dep_idx in dependency_map. get ( & constraint. sup ) . unwrap_or ( & vec ! [ ] ) {
502
+ if clean_bit_vec. remove ( dep_idx) {
503
+ dirty_list. push ( dep_idx) ;
504
+ }
491
505
}
492
506
}
507
+
493
508
debug ! ( "\n " ) ;
494
509
}
495
510
496
511
self . inferred_values = Some ( inferred_values) ;
497
512
}
498
513
514
+ /// Builds up a map from each region variable X to a vector with the
515
+ /// indices of constraints that need to be re-evaluated when X changes.
516
+ /// These are constraints like Y: X @ P -- so if X changed, we may
517
+ /// need to grow Y.
518
+ fn build_dependency_map ( & self ) -> HashMap < RegionVid , Vec < usize > > {
519
+ let mut map = HashMap :: new ( ) ;
520
+
521
+ for ( idx, constraint) in self . constraints . iter ( ) . enumerate ( ) {
522
+ map. entry ( constraint. sub ) . or_insert ( Vec :: new ( ) ) . push ( idx) ;
523
+ }
524
+
525
+ map
526
+ }
527
+
499
528
/// Once regions have been propagated, this method is used to see
500
529
/// whether the "type tests" produced by typeck were satisfied;
501
530
/// type tests encode type-outlives relationships like `T:
0 commit comments