88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ use std:: collections:: HashMap ;
12+
1113use super :: universal_regions:: UniversalRegions ;
1214use rustc:: hir:: def_id:: DefId ;
1315use rustc:: infer:: InferCtxt ;
@@ -22,6 +24,7 @@ use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegi
2224use rustc:: traits:: ObligationCause ;
2325use rustc:: ty:: { self , RegionVid , Ty , TypeFoldable } ;
2426use rustc:: util:: common:: ErrorReported ;
27+ use rustc_data_structures:: bitvec:: BitVector ;
2528use rustc_data_structures:: indexed_vec:: IndexVec ;
2629use rustc_errors:: DiagnosticBuilder ;
2730use std:: fmt;
@@ -452,8 +455,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
452455 /// satisfied. Note that some values may grow **too** large to be
453456 /// feasible, but we check this later.
454457 fn propagate_constraints ( & mut self , mir : & Mir < ' tcx > ) {
455- let mut changed = true ;
456-
457458 debug ! ( "propagate_constraints()" ) ;
458459 debug ! ( "propagate_constraints: constraints={:#?}" , {
459460 let mut constraints: Vec <_> = self . constraints. iter( ) . collect( ) ;
@@ -465,37 +466,65 @@ impl<'tcx> RegionInferenceContext<'tcx> {
465466 // constraints we have accumulated.
466467 let mut inferred_values = self . liveness_constraints . clone ( ) ;
467468
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) ;
486483
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+ }
491505 }
492506 }
507+
493508 debug ! ( "\n " ) ;
494509 }
495510
496511 self . inferred_values = Some ( inferred_values) ;
497512 }
498513
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+
499528 /// Once regions have been propagated, this method is used to see
500529 /// whether the "type tests" produced by typeck were satisfied;
501530 /// type tests encode type-outlives relationships like `T:
0 commit comments