@@ -67,6 +67,12 @@ pub struct RegionInferenceContext<'tcx> {
67
67
/// compute the values of each region.
68
68
constraint_sccs : Rc < Sccs < RegionVid , ConstraintSccIndex > > ,
69
69
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
+
70
76
/// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
71
77
/// `B: A`. This is used to compute the universal regions that are required
72
78
/// to outlive a given SCC. Computed lazily.
@@ -277,7 +283,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
277
283
scc_values. merge_liveness ( scc, region, & liveness_constraints) ;
278
284
}
279
285
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) ;
281
290
282
291
let scc_representatives = Self :: compute_scc_representatives ( & constraint_sccs, & definitions) ;
283
292
@@ -290,6 +299,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
290
299
constraints,
291
300
constraint_graph,
292
301
constraint_sccs,
302
+ scc_dependency_order,
293
303
rev_scc_graph : None ,
294
304
member_constraints,
295
305
member_constraints_applied : Vec :: new ( ) ,
@@ -307,6 +317,43 @@ impl<'tcx> RegionInferenceContext<'tcx> {
307
317
result
308
318
}
309
319
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
+
310
357
/// Each SCC is the combination of many region variables which
311
358
/// have been equated. Therefore, we can associate a universe with
312
359
/// each SCC which is minimum of all the universes of its
@@ -315,10 +362,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
315
362
/// SCC could have as well. This implies that the SCC must have
316
363
/// the minimum, or narrowest, universe.
317
364
fn compute_scc_universes (
318
- constraints_scc : & Sccs < RegionVid , ConstraintSccIndex > ,
365
+ constraint_sccs : & Sccs < RegionVid , ConstraintSccIndex > ,
366
+ scc_dependency_order : & [ ConstraintSccIndex ] ,
319
367
definitions : & IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
320
368
) -> IndexVec < ConstraintSccIndex , ty:: UniverseIndex > {
321
- let num_sccs = constraints_scc . num_sccs ( ) ;
369
+ let num_sccs = constraint_sccs . num_sccs ( ) ;
322
370
let mut scc_universes = IndexVec :: from_elem_n ( ty:: UniverseIndex :: MAX , num_sccs) ;
323
371
324
372
debug ! ( "compute_scc_universes()" ) ;
@@ -327,7 +375,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
327
375
// that contains R is "no bigger" than U. This effectively sets the universe
328
376
// for each SCC to be the minimum of the regions within.
329
377
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) ;
331
379
let scc_universe = & mut scc_universes[ scc] ;
332
380
let scc_min = std:: cmp:: min ( region_definition. universe , * scc_universe) ;
333
381
if scc_min != * scc_universe {
@@ -372,8 +420,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
372
420
// constraint lowers the universe of `R1` to `U0`, which in turn
373
421
// means that the `R1: !1` constraint will (later) cause
374
422
// `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) {
377
425
let scc_universe_a = scc_universes[ scc_a] ;
378
426
let scc_universe_b = scc_universes[ scc_b] ;
379
427
let scc_universe_min = std:: cmp:: min ( scc_universe_a, scc_universe_b) ;
@@ -616,47 +664,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
616
664
// SCC. For each SCC, we visit its successors and compute
617
665
// their values, then we union all those values to get our
618
666
// 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] ) ;
622
669
}
623
670
624
671
// Sort the applied member constraints so we can binary search
625
672
// through them later.
626
673
self . member_constraints_applied . sort_by_key ( |applied| applied. member_region_scc ) ;
627
674
}
628
675
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
-
642
676
/// 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 ) {
651
681
let constraint_sccs = self . constraint_sccs . clone ( ) ;
652
682
653
683
// Walk each SCC `B` such that `A: B`...
654
684
for & scc_b in constraint_sccs. successors ( scc_a) {
655
685
debug ! ( "propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}" , scc_a, scc_b) ;
656
686
657
- // ...compute the value of `B`...
658
- self . propagate_constraint_sccs_if_new ( scc_b, visited) ;
659
-
660
687
// ...and add elements from `B` into `A`. One complication
661
688
// arises because of universes: If `B` contains something
662
689
// that `A` cannot name, then `A` can only contain `B` if
0 commit comments