@@ -321,10 +321,75 @@ impl<'tcx> RegionInferenceContext<'tcx> {
321
321
let num_sccs = constraints_scc. num_sccs ( ) ;
322
322
let mut scc_universes = IndexVec :: from_elem_n ( ty:: UniverseIndex :: MAX , num_sccs) ;
323
323
324
+ debug ! ( "compute_scc_universes()" ) ;
325
+
326
+ // For each region R in universe U, ensure that the universe for the SCC
327
+ // that contains R is "no bigger" than U. This effectively sets the universe
328
+ // for each SCC to be the minimum of the regions within.
324
329
for ( region_vid, region_definition) in definitions. iter_enumerated ( ) {
325
330
let scc = constraints_scc. scc ( region_vid) ;
326
331
let scc_universe = & mut scc_universes[ scc] ;
327
- * scc_universe = :: std:: cmp:: min ( * scc_universe, region_definition. universe ) ;
332
+ let scc_min = std:: cmp:: min ( region_definition. universe , * scc_universe) ;
333
+ if scc_min != * scc_universe {
334
+ * scc_universe = scc_min;
335
+ debug ! (
336
+ "compute_scc_universes: lowered universe of {scc:?} to {scc_min:?} \
337
+ because it contains {region_vid:?} in {region_universe:?}",
338
+ scc = scc,
339
+ scc_min = scc_min,
340
+ region_vid = region_vid,
341
+ region_universe = region_definition. universe,
342
+ ) ;
343
+ }
344
+ }
345
+
346
+ // Walk each SCC `A` and `B` such that `A: B`
347
+ // and ensure that universe(A) can see universe(B).
348
+ //
349
+ // This serves to enforce the 'empty/placeholder' hierarchy
350
+ // (described in more detail on `RegionKind`):
351
+ //
352
+ // ```
353
+ // static -----+
354
+ // | |
355
+ // empty(U0) placeholder(U1)
356
+ // | /
357
+ // empty(U1)
358
+ // ```
359
+ //
360
+ // In particular, imagine we have variables R0 in U0 and R1
361
+ // created in U1, and constraints like this;
362
+ //
363
+ // ```
364
+ // R1: !1 // R1 outlives the placeholder in U1
365
+ // R1: R0 // R1 outlives R0
366
+ // ```
367
+ //
368
+ // Here, we wish for R1 to be `'static`, because it
369
+ // cannot outlive `placeholder(U1)` and `empty(U0)` any other way.
370
+ //
371
+ // Thanks to this loop, what happens is that the `R1: R0`
372
+ // constraint lowers the universe of `R1` to `U0`, which in turn
373
+ // means that the `R1: !1` constraint will (later) cause
374
+ // `R1` to become `'static`.
375
+ for scc_a in constraints_scc. all_sccs ( ) {
376
+ for & scc_b in constraints_scc. successors ( scc_a) {
377
+ let scc_universe_a = scc_universes[ scc_a] ;
378
+ let scc_universe_b = scc_universes[ scc_b] ;
379
+ let scc_universe_min = std:: cmp:: min ( scc_universe_a, scc_universe_b) ;
380
+ if scc_universe_a != scc_universe_min {
381
+ scc_universes[ scc_a] = scc_universe_min;
382
+
383
+ debug ! (
384
+ "compute_scc_universes: lowered universe of {scc_a:?} to {scc_universe_min:?} \
385
+ because {scc_a:?}: {scc_b:?} and {scc_b:?} is in universe {scc_universe_b:?}",
386
+ scc_a = scc_a,
387
+ scc_b = scc_b,
388
+ scc_universe_min = scc_universe_min,
389
+ scc_universe_b = scc_universe_b
390
+ ) ;
391
+ }
392
+ }
328
393
}
329
394
330
395
debug ! ( "compute_scc_universes: scc_universe = {:#?}" , scc_universes) ;
@@ -1773,6 +1838,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1773
1838
/// Finds some region R such that `fr1: R` and `R` is live at `elem`.
1774
1839
crate fn find_sub_region_live_at ( & self , fr1 : RegionVid , elem : Location ) -> RegionVid {
1775
1840
debug ! ( "find_sub_region_live_at(fr1={:?}, elem={:?})" , fr1, elem) ;
1841
+ debug ! ( "find_sub_region_live_at: {:?} is in scc {:?}" , fr1, self . constraint_sccs. scc( fr1) ) ;
1842
+ debug ! (
1843
+ "find_sub_region_live_at: {:?} is in universe {:?}" ,
1844
+ fr1,
1845
+ self . scc_universes[ self . constraint_sccs. scc( fr1) ]
1846
+ ) ;
1776
1847
self . find_constraint_paths_between_regions ( fr1, |r| {
1777
1848
// First look for some `r` such that `fr1: r` and `r` is live at `elem`
1778
1849
debug ! (
@@ -1794,13 +1865,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1794
1865
. or_else ( || {
1795
1866
// If we fail to find THAT, it may be that `fr1` is a
1796
1867
// placeholder that cannot "fit" into its SCC. In that
1797
- // case, there should be some `r` where `fr1: r`, both
1798
- // `fr1` and `r` are in the same SCC, and `fr1` is a
1868
+ // case, there should be some `r` where `fr1: r` and `fr1` is a
1799
1869
// placeholder that `r` cannot name. We can blame that
1800
1870
// edge.
1871
+ //
1872
+ // Remember that if `R1: R2`, then the universe of R1
1873
+ // must be able to name the universe of R2, because R2 will
1874
+ // be at least `'empty(Universe(R2))`, and `R1` must be at
1875
+ // larger than that.
1801
1876
self . find_constraint_paths_between_regions ( fr1, |r| {
1802
- self . constraint_sccs . scc ( fr1) == self . constraint_sccs . scc ( r)
1803
- && self . cannot_name_placeholder ( r, fr1)
1877
+ self . cannot_name_placeholder ( r, fr1)
1804
1878
} )
1805
1879
} )
1806
1880
. map ( |( _path, r) | r)
0 commit comments