@@ -67,6 +67,12 @@ pub struct RegionInferenceContext<'tcx> {
6767 /// compute the values of each region.
6868 constraint_sccs : Rc < Sccs < RegionVid , ConstraintSccIndex > > ,
6969
70+ /// SCCs in "dependency order" (or "post order"), meaning that if S1 -> S2,
71+ /// then S2 appears first. If you process the SCCs in this order, then you
72+ /// are always ensured that when you proces a given SCC, all of its
73+ /// successors have been processed.
74+ scc_dependency_order : Vec < ConstraintSccIndex > ,
75+
7076 /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
7177 /// `B: A`. This is used to compute the universal regions that are required
7278 /// to outlive a given SCC. Computed lazily.
@@ -277,7 +283,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
277283 scc_values. merge_liveness ( scc, region, & liveness_constraints) ;
278284 }
279285
280- let scc_universes = Self :: compute_scc_universes ( & constraint_sccs, & definitions) ;
286+ let scc_dependency_order = Self :: compute_scc_dependency_order ( & constraint_sccs) ;
287+
288+ let scc_universes =
289+ Self :: compute_scc_universes ( & constraint_sccs, & scc_dependency_order, & definitions) ;
281290
282291 let scc_representatives = Self :: compute_scc_representatives ( & constraint_sccs, & definitions) ;
283292
@@ -290,6 +299,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
290299 constraints,
291300 constraint_graph,
292301 constraint_sccs,
302+ scc_dependency_order,
293303 rev_scc_graph : None ,
294304 member_constraints,
295305 member_constraints_applied : Vec :: new ( ) ,
@@ -307,6 +317,43 @@ impl<'tcx> RegionInferenceContext<'tcx> {
307317 result
308318 }
309319
320+ /// Returns a vector of all scc-ids in "dependency" or "post order". See the
321+ /// `scc_dependency_order` field for more details.
322+ fn compute_scc_dependency_order (
323+ constraints_scc : & Sccs < RegionVid , ConstraintSccIndex > ,
324+ ) -> Vec < ConstraintSccIndex > {
325+ let mut visited = & mut BitSet :: new_empty ( constraints_scc. num_sccs ( ) ) ;
326+ let mut output = vec ! [ ] ;
327+
328+ for scc in constraints_scc. all_sccs ( ) {
329+ Self :: compute_scc_dependency_order_if_new (
330+ constraints_scc,
331+ scc,
332+ & mut visited,
333+ & mut output,
334+ ) ;
335+ }
336+
337+ output
338+ }
339+
340+ fn compute_scc_dependency_order_if_new (
341+ constraints_scc : & Sccs < RegionVid , ConstraintSccIndex > ,
342+ index : ConstraintSccIndex ,
343+ visited : & mut BitSet < ConstraintSccIndex > ,
344+ output : & mut Vec < ConstraintSccIndex > ,
345+ ) {
346+ if !visited. insert ( index) {
347+ return ;
348+ }
349+
350+ for & succ in constraints_scc. successors ( index) {
351+ Self :: compute_scc_dependency_order_if_new ( constraints_scc, succ, visited, output) ;
352+ }
353+
354+ output. push ( index) ;
355+ }
356+
310357 /// Each SCC is the combination of many region variables which
311358 /// have been equated. Therefore, we can associate a universe with
312359 /// each SCC which is minimum of all the universes of its
@@ -315,10 +362,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
315362 /// SCC could have as well. This implies that the SCC must have
316363 /// the minimum, or narrowest, universe.
317364 fn compute_scc_universes (
318- constraints_scc : & Sccs < RegionVid , ConstraintSccIndex > ,
365+ constraint_sccs : & Sccs < RegionVid , ConstraintSccIndex > ,
366+ scc_dependency_order : & [ ConstraintSccIndex ] ,
319367 definitions : & IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
320368 ) -> IndexVec < ConstraintSccIndex , ty:: UniverseIndex > {
321- let num_sccs = constraints_scc . num_sccs ( ) ;
369+ let num_sccs = constraint_sccs . num_sccs ( ) ;
322370 let mut scc_universes = IndexVec :: from_elem_n ( ty:: UniverseIndex :: MAX , num_sccs) ;
323371
324372 debug ! ( "compute_scc_universes()" ) ;
@@ -327,7 +375,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
327375 // that contains R is "no bigger" than U. This effectively sets the universe
328376 // for each SCC to be the minimum of the regions within.
329377 for ( region_vid, region_definition) in definitions. iter_enumerated ( ) {
330- let scc = constraints_scc . scc ( region_vid) ;
378+ let scc = constraint_sccs . scc ( region_vid) ;
331379 let scc_universe = & mut scc_universes[ scc] ;
332380 let scc_min = std:: cmp:: min ( region_definition. universe , * scc_universe) ;
333381 if scc_min != * scc_universe {
@@ -372,8 +420,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
372420 // constraint lowers the universe of `R1` to `U0`, which in turn
373421 // means that the `R1: !1` constraint will (later) cause
374422 // `R1` to become `'static`.
375- for scc_a in constraints_scc . all_sccs ( ) {
376- for & scc_b in constraints_scc . successors ( scc_a) {
423+ for & scc_a in scc_dependency_order {
424+ for & scc_b in constraint_sccs . successors ( scc_a) {
377425 let scc_universe_a = scc_universes[ scc_a] ;
378426 let scc_universe_b = scc_universes[ scc_b] ;
379427 let scc_universe_min = std:: cmp:: min ( scc_universe_a, scc_universe_b) ;
@@ -616,47 +664,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
616664 // SCC. For each SCC, we visit its successors and compute
617665 // their values, then we union all those values to get our
618666 // own.
619- let visited = & mut BitSet :: new_empty ( self . constraint_sccs . num_sccs ( ) ) ;
620- for scc_index in self . constraint_sccs . all_sccs ( ) {
621- self . propagate_constraint_sccs_if_new ( scc_index, visited) ;
667+ for i in 0 ..self . scc_dependency_order . len ( ) {
668+ self . compute_value_for_scc ( self . scc_dependency_order [ i] ) ;
622669 }
623670
624671 // Sort the applied member constraints so we can binary search
625672 // through them later.
626673 self . member_constraints_applied . sort_by_key ( |applied| applied. member_region_scc ) ;
627674 }
628675
629- /// Computes the value of the SCC `scc_a` if it has not already
630- /// been computed. The `visited` parameter is a bitset
631- #[ inline]
632- fn propagate_constraint_sccs_if_new (
633- & mut self ,
634- scc_a : ConstraintSccIndex ,
635- visited : & mut BitSet < ConstraintSccIndex > ,
636- ) {
637- if visited. insert ( scc_a) {
638- self . propagate_constraint_sccs_new ( scc_a, visited) ;
639- }
640- }
641-
642676 /// Computes the value of the SCC `scc_a`, which has not yet been
643- /// computed. This works by first computing all successors of the
644- /// SCC (if they haven't been computed already) and then unioning
645- /// together their elements.
646- fn propagate_constraint_sccs_new (
647- & mut self ,
648- scc_a : ConstraintSccIndex ,
649- visited : & mut BitSet < ConstraintSccIndex > ,
650- ) {
677+ /// computed, by unioning the values of its successors.
678+ /// Assumes that all successors have been computed already
679+ /// (which is assured by iterating over SCCs in dependency order).
680+ fn compute_value_for_scc ( & mut self , scc_a : ConstraintSccIndex ) {
651681 let constraint_sccs = self . constraint_sccs . clone ( ) ;
652682
653683 // Walk each SCC `B` such that `A: B`...
654684 for & scc_b in constraint_sccs. successors ( scc_a) {
655685 debug ! ( "propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}" , scc_a, scc_b) ;
656686
657- // ...compute the value of `B`...
658- self . propagate_constraint_sccs_if_new ( scc_b, visited) ;
659-
660687 // ...and add elements from `B` into `A`. One complication
661688 // arises because of universes: If `B` contains something
662689 // that `A` cannot name, then `A` can only contain `B` if
0 commit comments