@@ -62,7 +62,7 @@ pub struct RegionTracker {
6262 /// The representative Region Variable Id for this SCC. We prefer
6363 /// placeholders over existentially quantified variables, otherwise
6464 /// it's the one with the smallest Region Variable ID.
65- representative : RegionVid ,
65+ pub ( crate ) representative : RegionVid ,
6666
6767 /// Is the current representative a placeholder?
6868 representative_is_placeholder : bool ,
@@ -97,7 +97,7 @@ impl scc::Annotation for RegionTracker {
9797}
9898
9999impl RegionTracker {
100- fn new ( rvid : RegionVid , definition : & RegionDefinition < ' _ > ) -> Self {
100+ pub ( crate ) fn new ( rvid : RegionVid , definition : & RegionDefinition < ' _ > ) -> Self {
101101 let ( representative_is_placeholder, representative_is_existential) = match definition. origin
102102 {
103103 rustc_infer:: infer:: NllRegionVariableOrigin :: FreeRegion => ( false , false ) ,
@@ -116,7 +116,9 @@ impl RegionTracker {
116116 representative_is_existential,
117117 }
118118 }
119- fn universe ( self ) -> UniverseIndex {
119+
120+ /// The smallest-indexed universe reachable from and/or in this SCC.
121+ fn min_universe ( self ) -> UniverseIndex {
120122 self . min_reachable_universe
121123 }
122124
@@ -132,8 +134,8 @@ impl RegionTracker {
132134
133135 /// Returns `true` if during the annotated SCC reaches a placeholder
134136 /// with a universe larger than the smallest reachable one, `false` otherwise.
135- pub fn has_incompatible_universes ( & self ) -> bool {
136- self . universe ( ) . cannot_name ( self . max_placeholder_universe_reached )
137+ pub ( crate ) fn has_incompatible_universes ( & self ) -> bool {
138+ self . min_universe ( ) . cannot_name ( self . max_placeholder_universe_reached )
137139 }
138140}
139141
@@ -163,7 +165,7 @@ pub struct RegionInferenceContext<'tcx> {
163165 /// The SCC computed from `constraints` and the constraint
164166 /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
165167 /// compute the values of each region.
166- constraint_sccs : Rc < ConstraintSccs > ,
168+ constraint_sccs : ConstraintSccs ,
167169
168170 /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
169171 /// `B: A`. This is used to compute the universal regions that are required
@@ -401,7 +403,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
401403 universal_regions : Rc < UniversalRegions < ' tcx > > ,
402404 placeholder_indices : Rc < PlaceholderIndices > ,
403405 universal_region_relations : Frozen < UniversalRegionRelations < ' tcx > > ,
404- outlives_constraints : OutlivesConstraintSet < ' tcx > ,
406+ mut outlives_constraints : OutlivesConstraintSet < ' tcx > ,
405407 member_constraints_in : MemberConstraintSet < ' tcx , RegionVid > ,
406408 universe_causes : FxIndexMap < ty:: UniverseIndex , UniverseInfo < ' tcx > > ,
407409 type_tests : Vec < TypeTest < ' tcx > > ,
@@ -419,17 +421,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
419421 . map ( |info| RegionDefinition :: new ( info. universe , info. origin ) )
420422 . collect ( ) ;
421423
422- let fr_static = universal_regions. fr_static ;
424+ let constraint_sccs =
425+ outlives_constraints. add_outlives_static ( & universal_regions, & definitions) ;
423426 let constraints = Frozen :: freeze ( outlives_constraints) ;
424427 let constraint_graph = Frozen :: freeze ( constraints. graph ( definitions. len ( ) ) ) ;
425- let constraint_sccs = {
426- let constraint_graph = constraints. graph ( definitions. len ( ) ) ;
427- let region_graph = & constraint_graph. region_graph ( & constraints, fr_static) ;
428- let sccs = ConstraintSccs :: new_with_annotation ( & region_graph, |r| {
429- RegionTracker :: new ( r, & definitions[ r] )
430- } ) ;
431- Rc :: new ( sccs)
432- } ;
433428
434429 if cfg ! ( debug_assertions) {
435430 sccs_info ( infcx, & constraint_sccs) ;
@@ -548,21 +543,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
548543 }
549544
550545 NllRegionVariableOrigin :: Placeholder ( placeholder) => {
551- // Each placeholder region is only visible from
552- // its universe `ui` and its extensions. So we
553- // can't just add it into `scc` unless the
554- // universe of the scc can name this region.
555- let scc_universe = self . scc_universe ( scc) ;
556- if scc_universe. can_name ( placeholder. universe ) {
557- self . scc_values . add_element ( scc, placeholder) ;
558- } else {
559- debug ! (
560- "init_free_and_bound_regions: placeholder {:?} is \
561- not compatible with universe {:?} of its SCC {:?}",
562- placeholder, scc_universe, scc,
563- ) ;
564- self . add_incompatible_universe ( scc) ;
565- }
546+ self . scc_values . add_element ( scc, placeholder) ;
566547 }
567548
568549 NllRegionVariableOrigin :: Existential { .. } => {
@@ -744,23 +725,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
744725 /// (which is assured by iterating over SCCs in dependency order).
745726 #[ instrument( skip( self ) , level = "debug" ) ]
746727 fn compute_value_for_scc ( & mut self , scc_a : ConstraintSccIndex ) {
747- let constraint_sccs = self . constraint_sccs . clone ( ) ;
748-
749728 // Walk each SCC `B` such that `A: B`...
750- for & scc_b in constraint_sccs. successors ( scc_a) {
729+ for & scc_b in self . constraint_sccs . successors ( scc_a) {
751730 debug ! ( ?scc_b) ;
752-
753- // ...and add elements from `B` into `A`. One complication
754- // arises because of universes: If `B` contains something
755- // that `A` cannot name, then `A` can only contain `B` if
756- // it outlives static.
757- if self . universe_compatible ( scc_b, scc_a) {
758- // `A` can name everything that is in `B`, so just
759- // merge the bits.
760- self . scc_values . add_region ( scc_a, scc_b) ;
761- } else {
762- self . add_incompatible_universe ( scc_a) ;
763- }
731+ self . scc_values . add_region ( scc_a, scc_b) ;
764732 }
765733
766734 // Now take member constraints into account.
@@ -814,7 +782,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
814782 // If the member region lives in a higher universe, we currently choose
815783 // the most conservative option by leaving it unchanged.
816784
817- if !self . constraint_sccs ( ) . annotation ( scc) . universe ( ) . is_root ( ) {
785+ if !self . constraint_sccs ( ) . annotation ( scc) . min_universe ( ) . is_root ( ) {
818786 return ;
819787 }
820788
@@ -886,35 +854,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
886854 /// in `scc_a`. Used during constraint propagation, and only once
887855 /// the value of `scc_b` has been computed.
888856 fn universe_compatible ( & self , scc_b : ConstraintSccIndex , scc_a : ConstraintSccIndex ) -> bool {
889- let universe_a = self . constraint_sccs ( ) . annotation ( scc_a) . universe ( ) ;
890- let universe_b = self . constraint_sccs ( ) . annotation ( scc_b) . universe ( ) ;
857+ let a_annotation = self . constraint_sccs ( ) . annotation ( scc_a) ;
858+ let b_annotation = self . constraint_sccs ( ) . annotation ( scc_b) ;
859+ let a_universe = a_annotation. min_universe ( ) ;
891860
892- // Quick check: if scc_b's declared universe is a subset of
861+ // If scc_b's declared universe is a subset of
893862 // scc_a's declared universe (typically, both are ROOT), then
894863 // it cannot contain any problematic universe elements.
895- if universe_a . can_name ( universe_b ) {
864+ if a_universe . can_name ( b_annotation . min_universe ( ) ) {
896865 return true ;
897866 }
898867
899- // Otherwise, we have to iterate over the universe elements in
900- // B's value, and check whether all of them are nameable
901- // from universe_a
902- self . scc_values . placeholders_contained_in ( scc_b) . all ( |p| universe_a. can_name ( p. universe ) )
903- }
904-
905- /// Extend `scc` so that it can outlive some placeholder region
906- /// from a universe it can't name; at present, the only way for
907- /// this to be true is if `scc` outlives `'static`. This is
908- /// actually stricter than necessary: ideally, we'd support bounds
909- /// like `for<'a: 'b>` that might then allow us to approximate
910- /// `'a` with `'b` and not `'static`. But it will have to do for
911- /// now.
912- fn add_incompatible_universe ( & mut self , scc : ConstraintSccIndex ) {
913- debug ! ( "add_incompatible_universe(scc={:?})" , scc) ;
914-
915- let fr_static = self . universal_regions . fr_static ;
916- self . scc_values . add_all_points ( scc) ;
917- self . scc_values . add_element ( scc, fr_static) ;
868+ // Otherwise, there can be no placeholder in `b` with a too high
869+ // universe index to name from `a`.
870+ a_universe. can_name ( b_annotation. max_placeholder_universe_reached )
918871 }
919872
920873 /// Once regions have been propagated, this method is used to see
@@ -1022,7 +975,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1022975 "lower_bound = {:?} r_scc={:?} universe={:?}" ,
1023976 lower_bound,
1024977 r_scc,
1025- self . constraint_sccs. annotation( r_scc) . universe ( )
978+ self . constraint_sccs. annotation( r_scc) . min_universe ( )
1026979 ) ;
1027980
1028981 // If the type test requires that `T: 'a` where `'a` is a
@@ -1539,7 +1492,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15391492 /// The minimum universe of any variable reachable from this
15401493 /// SCC, inside or outside of it.
15411494 fn scc_universe ( & self , scc : ConstraintSccIndex ) -> UniverseIndex {
1542- self . constraint_sccs ( ) . annotation ( scc) . universe ( )
1495+ self . constraint_sccs ( ) . annotation ( scc) . min_universe ( )
15431496 }
15441497 /// Checks the final value for the free region `fr` to see if it
15451498 /// grew too large. In particular, examine what `end(X)` points
@@ -1896,6 +1849,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
18961849
18971850 // This loop can be hot.
18981851 for constraint in outgoing_edges_from_graph {
1852+ if matches ! ( constraint. category, ConstraintCategory :: IllegalUniverse ) {
1853+ debug ! ( "Ignoring illegal universe constraint: {constraint:?}" ) ;
1854+ continue ;
1855+ }
18991856 handle_constraint ( constraint) ;
19001857 }
19011858
0 commit comments