55//! This logic is provisional and should be removed once the trait
66//! solver can handle this kind of constraint.
77use rustc_data_structures:: frozen:: Frozen ;
8- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
8+ use rustc_data_structures:: fx:: FxIndexMap ;
99use rustc_data_structures:: graph:: scc;
1010use rustc_data_structures:: graph:: scc:: Sccs ;
1111use rustc_index:: IndexVec ;
@@ -18,7 +18,7 @@ use crate::consumers::OutlivesConstraint;
1818use crate :: diagnostics:: UniverseInfo ;
1919use crate :: member_constraints:: MemberConstraintSet ;
2020use crate :: region_infer:: values:: { LivenessValues , PlaceholderIndices } ;
21- use crate :: region_infer:: { ConstraintSccs , RegionDefinition , TypeTest } ;
21+ use crate :: region_infer:: { ConstraintSccs , RegionDefinition , Representative , TypeTest } ;
2222use crate :: ty:: VarianceDiagInfo ;
2323use crate :: type_check:: free_region_relations:: UniversalRegionRelations ;
2424use crate :: type_check:: { Locations , MirTypeckRegionConstraints } ;
@@ -32,7 +32,7 @@ pub(crate) struct LoweredConstraints<'tcx> {
3232 pub ( crate ) definitions : Frozen < IndexVec < RegionVid , RegionDefinition < ' tcx > > > ,
3333 pub ( crate ) scc_annotations : IndexVec < ConstraintSccIndex , RegionTracker > ,
3434 pub ( crate ) member_constraints : MemberConstraintSet < ' tcx , RegionVid > ,
35- pub ( crate ) outlives_constraints : OutlivesConstraintSet < ' tcx > ,
35+ pub ( crate ) outlives_constraints : Frozen < OutlivesConstraintSet < ' tcx > > ,
3636 pub ( crate ) type_tests : Vec < TypeTest < ' tcx > > ,
3737 pub ( crate ) liveness_constraints : LivenessValues ,
3838 pub ( crate ) universe_causes : FxIndexMap < UniverseIndex , UniverseInfo < ' tcx > > ,
@@ -73,45 +73,35 @@ pub(crate) struct RegionTracker {
7373 /// This includes placeholders within this SCC.
7474 max_placeholder_universe_reached : UniverseIndex ,
7575
76- /// The smallest universe index reachable form the nodes of this SCC.
77- min_reachable_universe : UniverseIndex ,
76+ /// The smallest universe nameable from this SCC.
77+ /// It is the smallest of all the largest nameable universes
78+ /// of any region reachable from it.
79+ max_nameable_universe : UniverseIndex ,
7880
79- /// The representative Region Variable Id for this SCC. We prefer
80- /// placeholders over existentially quantified variables, otherwise
81- /// it's the one with the smallest Region Variable ID.
82- pub ( crate ) representative : RegionVid ,
83-
84- /// Is the current representative a placeholder?
85- representative_is_placeholder : bool ,
86-
87- /// Is the current representative existentially quantified?
88- representative_is_existential : bool ,
81+ /// The representative Region Variable Id for this SCC.
82+ pub ( crate ) representative : Representative ,
8983}
9084
9185impl RegionTracker {
9286 pub ( crate ) fn new ( rvid : RegionVid , definition : & RegionDefinition < ' _ > ) -> Self {
93- let ( representative_is_placeholder, representative_is_existential) = match definition. origin
94- {
95- NllRegionVariableOrigin :: FreeRegion => ( false , false ) ,
96- NllRegionVariableOrigin :: Placeholder ( _) => ( true , false ) ,
97- NllRegionVariableOrigin :: Existential { .. } => ( false , true ) ,
98- } ;
99-
10087 let placeholder_universe =
101- if representative_is_placeholder { definition. universe } else { UniverseIndex :: ROOT } ;
88+ if matches ! ( definition. origin, NllRegionVariableOrigin :: Placeholder ( _) ) {
89+ definition. universe
90+ } else {
91+ UniverseIndex :: ROOT
92+ } ;
10293
10394 Self {
10495 max_placeholder_universe_reached : placeholder_universe,
105- min_reachable_universe : definition. universe ,
106- representative : rvid,
107- representative_is_placeholder,
108- representative_is_existential,
96+ max_nameable_universe : definition. universe ,
97+ representative : Representative :: new ( rvid, definition) ,
10998 }
11099 }
111100
112- /// The smallest-indexed universe reachable from and/or in this SCC.
113- pub ( crate ) fn min_universe ( self ) -> UniverseIndex {
114- self . min_reachable_universe
101+ /// The largest universe this SCC can name. It's the smallest
102+ /// largest nameable uninverse of any reachable region.
103+ pub ( crate ) fn max_nameable_universe ( self ) -> UniverseIndex {
104+ self . max_nameable_universe
115105 }
116106
117107 fn merge_min_max_seen ( & mut self , other : & Self ) {
@@ -120,40 +110,28 @@ impl RegionTracker {
120110 other. max_placeholder_universe_reached ,
121111 ) ;
122112
123- self . min_reachable_universe =
124- std:: cmp:: min ( self . min_reachable_universe , other. min_reachable_universe ) ;
113+ self . max_nameable_universe =
114+ std:: cmp:: min ( self . max_nameable_universe , other. max_nameable_universe ) ;
125115 }
126116
127117 /// Returns `true` if during the annotated SCC reaches a placeholder
128118 /// with a universe larger than the smallest reachable one, `false` otherwise.
129119 pub ( crate ) fn has_incompatible_universes ( & self ) -> bool {
130- self . min_universe ( ) . cannot_name ( self . max_placeholder_universe_reached )
120+ self . max_nameable_universe ( ) . cannot_name ( self . max_placeholder_universe_reached )
131121 }
132122
133- /// Determine if the tracked universes of the two SCCs
134- /// are compatible.
123+ /// Determine if the tracked universes of the two SCCs are compatible.
135124 pub ( crate ) fn universe_compatible_with ( & self , other : Self ) -> bool {
136- self . min_universe ( ) . can_name ( other. min_universe ( ) )
137- || self . min_universe ( ) . can_name ( other. max_placeholder_universe_reached )
125+ self . max_nameable_universe ( ) . can_name ( other. max_nameable_universe ( ) )
126+ || self . max_nameable_universe ( ) . can_name ( other. max_placeholder_universe_reached )
138127 }
139128}
140129
141130impl scc:: Annotation for RegionTracker {
142- fn merge_scc ( mut self , mut other : Self ) -> Self {
143- // Prefer any placeholder over any existential
144- if other. representative_is_placeholder && self . representative_is_existential {
145- other. merge_min_max_seen ( & self ) ;
146- return other;
147- }
148-
149- if self . representative_is_placeholder && other. representative_is_existential
150- || ( self . representative <= other. representative )
151- {
152- self . merge_min_max_seen ( & other) ;
153- return self ;
154- }
155- other. merge_min_max_seen ( & self ) ;
156- other
131+ fn merge_scc ( mut self , other : Self ) -> Self {
132+ self . representative = self . representative . merge_scc ( other. representative ) ;
133+ self . merge_min_max_seen ( & other) ;
134+ self
157135 }
158136
159137 fn merge_reached ( mut self , other : Self ) -> Self {
@@ -164,7 +142,7 @@ impl scc::Annotation for RegionTracker {
164142}
165143
166144/// Determines if the region variable definitions contain
167- /// placeholers , and compute them for later use.
145+ /// placeholders , and compute them for later use.
168146fn region_definitions < ' tcx > (
169147 universal_regions : & UniversalRegions < ' tcx > ,
170148 infcx : & BorrowckInferCtxt < ' tcx > ,
@@ -190,7 +168,7 @@ fn region_definitions<'tcx>(
190168 ( Frozen :: freeze ( definitions) , has_placeholders)
191169}
192170
193- /// This method handles Universe errors by rewriting the constraint
171+ /// This method handles placeholders by rewriting the constraint
194172/// graph. For each strongly connected component in the constraint
195173/// graph such that there is a series of constraints
196174/// A: B: C: ... : X where
@@ -200,19 +178,9 @@ fn region_definitions<'tcx>(
200178/// eventually go away.
201179///
202180/// For a more precise definition, see the documentation for
203- /// [`RegionTracker`] and its methods!.
204- ///
205- /// Since universes can also be involved in errors (if one placeholder
206- /// transitively outlives another), this function also flags those.
207- ///
208- /// Additionally, it similarly rewrites type-tests.
209- ///
210- /// This edge case used to be handled during constraint propagation
211- /// by iterating over the strongly connected components in the constraint
212- /// graph while maintaining a set of bookkeeping mappings similar
213- /// to what is stored in `RegionTracker` and manually adding 'sttaic as
214- /// needed.
181+ /// [`RegionTracker`] and its methods!
215182///
183+ /// This edge case used to be handled during constraint propagation.
216184/// It was rewritten as part of the Polonius project with the goal of moving
217185/// higher-kindedness concerns out of the path of the borrow checker,
218186/// for two reasons:
@@ -267,36 +235,37 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
267235 )
268236 } ;
269237
238+ let mut scc_annotations = SccAnnotations :: init ( & definitions) ;
239+ let constraint_sccs = compute_sccs ( & outlives_constraints, & mut scc_annotations) ;
240+
270241 // This code structure is a bit convoluted because it allows for a planned
271242 // future change where the early return here has a different type of annotation
272243 // that does much less work.
273244 if !has_placeholders {
274245 debug ! ( "No placeholder regions found; skipping rewriting logic!" ) ;
275- let mut scc_annotations = SccAnnotations :: init ( & definitions) ;
276- let constraint_sccs = compute_sccs ( & outlives_constraints, & mut scc_annotations) ;
277246
278247 return LoweredConstraints {
279248 type_tests,
280249 member_constraints,
281250 constraint_sccs,
282251 scc_annotations : scc_annotations. scc_to_annotation ,
283252 definitions,
284- outlives_constraints,
253+ outlives_constraints : Frozen :: freeze ( outlives_constraints ) ,
285254 liveness_constraints,
286255 universe_causes,
287256 placeholder_indices,
288257 } ;
289258 }
290259 debug ! ( "Placeholders present; activating placeholder handling logic!" ) ;
291260
292- let mut annotations = SccAnnotations :: init ( & definitions) ;
293- let sccs = compute_sccs ( & outlives_constraints, & mut annotations) ;
294-
295- let outlives_static =
296- rewrite_outlives ( & sccs, & annotations, fr_static, & mut outlives_constraints) ;
261+ let added_constraints = rewrite_placeholder_outlives (
262+ & constraint_sccs,
263+ & scc_annotations,
264+ fr_static,
265+ & mut outlives_constraints,
266+ ) ;
297267
298- let ( sccs, scc_annotations) = if !outlives_static. is_empty ( ) {
299- debug ! ( "The following SCCs had :'static constraints added: {:?}" , outlives_static) ;
268+ let ( constraint_sccs, scc_annotations) = if added_constraints {
300269 let mut annotations = SccAnnotations :: init ( & definitions) ;
301270
302271 // We changed the constraint set and so must recompute SCCs.
@@ -307,31 +276,31 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
307276 } else {
308277 // If we didn't add any back-edges; no more work needs doing
309278 debug ! ( "No constraints rewritten!" ) ;
310- ( sccs , annotations . scc_to_annotation )
279+ ( constraint_sccs , scc_annotations . scc_to_annotation )
311280 } ;
312281
313282 LoweredConstraints {
314- constraint_sccs : sccs ,
283+ constraint_sccs,
315284 definitions,
316285 scc_annotations,
317286 member_constraints,
318- outlives_constraints,
287+ outlives_constraints : Frozen :: freeze ( outlives_constraints ) ,
319288 type_tests,
320289 liveness_constraints,
321290 universe_causes,
322291 placeholder_indices,
323292 }
324293}
325294
326- fn rewrite_outlives < ' tcx > (
295+ fn rewrite_placeholder_outlives < ' tcx > (
327296 sccs : & Sccs < RegionVid , ConstraintSccIndex > ,
328297 annotations : & SccAnnotations < ' _ , ' _ , RegionTracker > ,
329298 fr_static : RegionVid ,
330299 outlives_constraints : & mut OutlivesConstraintSet < ' tcx > ,
331- ) -> FxHashSet < ConstraintSccIndex > {
332- // Changed to `true` if we added any constraints to `self` and need to
300+ ) -> bool {
301+ // Changed to `true` if we added any constraints and need to
333302 // recompute SCCs.
334- let mut outlives_static = FxHashSet :: default ( ) ;
303+ let mut added_constraints = false ;
335304
336305 let annotations = & annotations. scc_to_annotation ;
337306
@@ -354,9 +323,8 @@ fn rewrite_outlives<'tcx>(
354323 // needed for correctness, since an SCC upstream of another with
355324 // a universe violation will "infect" its downstream SCCs to also
356325 // outlive static.
357- outlives_static. insert ( scc) ;
358326 let scc_representative_outlives_static = OutlivesConstraint {
359- sup : annotation. representative ,
327+ sup : annotation. representative . rvid ( ) ,
360328 sub : fr_static,
361329 category : ConstraintCategory :: IllegalUniverse ,
362330 locations : Locations :: All ( rustc_span:: DUMMY_SP ) ,
@@ -365,7 +333,9 @@ fn rewrite_outlives<'tcx>(
365333 from_closure : false ,
366334 } ;
367335 outlives_constraints. push ( scc_representative_outlives_static) ;
336+ added_constraints = true ;
337+ debug ! ( "Added {:?}: 'static!" , annotation. representative. rvid( ) ) ;
368338 }
369339 }
370- outlives_static
340+ added_constraints
371341}
0 commit comments