@@ -321,10 +321,75 @@ impl<'tcx> RegionInferenceContext<'tcx> {
321321 let num_sccs = constraints_scc. num_sccs ( ) ;
322322 let mut scc_universes = IndexVec :: from_elem_n ( ty:: UniverseIndex :: MAX , num_sccs) ;
323323
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.
324329 for ( region_vid, region_definition) in definitions. iter_enumerated ( ) {
325330 let scc = constraints_scc. scc ( region_vid) ;
326331 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+ }
328393 }
329394
330395 debug ! ( "compute_scc_universes: scc_universe = {:#?}" , scc_universes) ;
@@ -1773,6 +1838,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17731838 /// Finds some region R such that `fr1: R` and `R` is live at `elem`.
17741839 crate fn find_sub_region_live_at ( & self , fr1 : RegionVid , elem : Location ) -> RegionVid {
17751840 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+ ) ;
17761847 self . find_constraint_paths_between_regions ( fr1, |r| {
17771848 // First look for some `r` such that `fr1: r` and `r` is live at `elem`
17781849 debug ! (
@@ -1794,13 +1865,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17941865 . or_else ( || {
17951866 // If we fail to find THAT, it may be that `fr1` is a
17961867 // 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
17991869 // placeholder that `r` cannot name. We can blame that
18001870 // 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.
18011876 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)
18041878 } )
18051879 } )
18061880 . map ( |( _path, r) | r)
0 commit comments