5
5
//! This logic is provisional and should be removed once the trait
6
6
//! solver can handle this kind of constraint.
7
7
use rustc_data_structures:: frozen:: Frozen ;
8
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
8
+ use rustc_data_structures:: fx:: FxIndexMap ;
9
9
use rustc_data_structures:: graph:: scc;
10
10
use rustc_data_structures:: graph:: scc:: Sccs ;
11
11
use rustc_index:: IndexVec ;
@@ -18,7 +18,7 @@ use crate::consumers::OutlivesConstraint;
18
18
use crate :: diagnostics:: UniverseInfo ;
19
19
use crate :: member_constraints:: MemberConstraintSet ;
20
20
use crate :: region_infer:: values:: { LivenessValues , PlaceholderIndices } ;
21
- use crate :: region_infer:: { ConstraintSccs , RegionDefinition , TypeTest } ;
21
+ use crate :: region_infer:: { ConstraintSccs , RegionDefinition , Representative , TypeTest } ;
22
22
use crate :: ty:: VarianceDiagInfo ;
23
23
use crate :: type_check:: free_region_relations:: UniversalRegionRelations ;
24
24
use crate :: type_check:: { Locations , MirTypeckRegionConstraints } ;
@@ -32,7 +32,7 @@ pub(crate) struct LoweredConstraints<'tcx> {
32
32
pub ( crate ) definitions : Frozen < IndexVec < RegionVid , RegionDefinition < ' tcx > > > ,
33
33
pub ( crate ) scc_annotations : IndexVec < ConstraintSccIndex , RegionTracker > ,
34
34
pub ( crate ) member_constraints : MemberConstraintSet < ' tcx , RegionVid > ,
35
- pub ( crate ) outlives_constraints : OutlivesConstraintSet < ' tcx > ,
35
+ pub ( crate ) outlives_constraints : Frozen < OutlivesConstraintSet < ' tcx > > ,
36
36
pub ( crate ) type_tests : Vec < TypeTest < ' tcx > > ,
37
37
pub ( crate ) liveness_constraints : LivenessValues ,
38
38
pub ( crate ) universe_causes : FxIndexMap < UniverseIndex , UniverseInfo < ' tcx > > ,
@@ -73,45 +73,35 @@ pub(crate) struct RegionTracker {
73
73
/// This includes placeholders within this SCC.
74
74
max_placeholder_universe_reached : UniverseIndex ,
75
75
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 ,
78
80
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 ,
89
83
}
90
84
91
85
impl RegionTracker {
92
86
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
-
100
87
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
+ } ;
102
93
103
94
Self {
104
95
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) ,
109
98
}
110
99
}
111
100
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
115
105
}
116
106
117
107
fn merge_min_max_seen ( & mut self , other : & Self ) {
@@ -120,40 +110,28 @@ impl RegionTracker {
120
110
other. max_placeholder_universe_reached ,
121
111
) ;
122
112
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 ) ;
125
115
}
126
116
127
117
/// Returns `true` if during the annotated SCC reaches a placeholder
128
118
/// with a universe larger than the smallest reachable one, `false` otherwise.
129
119
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 )
131
121
}
132
122
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.
135
124
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 )
138
127
}
139
128
}
140
129
141
130
impl 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
157
135
}
158
136
159
137
fn merge_reached ( mut self , other : Self ) -> Self {
@@ -164,7 +142,7 @@ impl scc::Annotation for RegionTracker {
164
142
}
165
143
166
144
/// Determines if the region variable definitions contain
167
- /// placeholers , and compute them for later use.
145
+ /// placeholders , and compute them for later use.
168
146
fn region_definitions < ' tcx > (
169
147
universal_regions : & UniversalRegions < ' tcx > ,
170
148
infcx : & BorrowckInferCtxt < ' tcx > ,
@@ -190,7 +168,7 @@ fn region_definitions<'tcx>(
190
168
( Frozen :: freeze ( definitions) , has_placeholders)
191
169
}
192
170
193
- /// This method handles Universe errors by rewriting the constraint
171
+ /// This method handles placeholders by rewriting the constraint
194
172
/// graph. For each strongly connected component in the constraint
195
173
/// graph such that there is a series of constraints
196
174
/// A: B: C: ... : X where
@@ -200,19 +178,9 @@ fn region_definitions<'tcx>(
200
178
/// eventually go away.
201
179
///
202
180
/// 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!
215
182
///
183
+ /// This edge case used to be handled during constraint propagation.
216
184
/// It was rewritten as part of the Polonius project with the goal of moving
217
185
/// higher-kindedness concerns out of the path of the borrow checker,
218
186
/// for two reasons:
@@ -267,36 +235,37 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
267
235
)
268
236
} ;
269
237
238
+ let mut scc_annotations = SccAnnotations :: init ( & definitions) ;
239
+ let constraint_sccs = compute_sccs ( & outlives_constraints, & mut scc_annotations) ;
240
+
270
241
// This code structure is a bit convoluted because it allows for a planned
271
242
// future change where the early return here has a different type of annotation
272
243
// that does much less work.
273
244
if !has_placeholders {
274
245
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) ;
277
246
278
247
return LoweredConstraints {
279
248
type_tests,
280
249
member_constraints,
281
250
constraint_sccs,
282
251
scc_annotations : scc_annotations. scc_to_annotation ,
283
252
definitions,
284
- outlives_constraints,
253
+ outlives_constraints : Frozen :: freeze ( outlives_constraints ) ,
285
254
liveness_constraints,
286
255
universe_causes,
287
256
placeholder_indices,
288
257
} ;
289
258
}
290
259
debug ! ( "Placeholders present; activating placeholder handling logic!" ) ;
291
260
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
+ ) ;
297
267
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 {
300
269
let mut annotations = SccAnnotations :: init ( & definitions) ;
301
270
302
271
// We changed the constraint set and so must recompute SCCs.
@@ -307,31 +276,31 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
307
276
} else {
308
277
// If we didn't add any back-edges; no more work needs doing
309
278
debug ! ( "No constraints rewritten!" ) ;
310
- ( sccs , annotations . scc_to_annotation )
279
+ ( constraint_sccs , scc_annotations . scc_to_annotation )
311
280
} ;
312
281
313
282
LoweredConstraints {
314
- constraint_sccs : sccs ,
283
+ constraint_sccs,
315
284
definitions,
316
285
scc_annotations,
317
286
member_constraints,
318
- outlives_constraints,
287
+ outlives_constraints : Frozen :: freeze ( outlives_constraints ) ,
319
288
type_tests,
320
289
liveness_constraints,
321
290
universe_causes,
322
291
placeholder_indices,
323
292
}
324
293
}
325
294
326
- fn rewrite_outlives < ' tcx > (
295
+ fn rewrite_placeholder_outlives < ' tcx > (
327
296
sccs : & Sccs < RegionVid , ConstraintSccIndex > ,
328
297
annotations : & SccAnnotations < ' _ , ' _ , RegionTracker > ,
329
298
fr_static : RegionVid ,
330
299
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
333
302
// recompute SCCs.
334
- let mut outlives_static = FxHashSet :: default ( ) ;
303
+ let mut added_constraints = false ;
335
304
336
305
let annotations = & annotations. scc_to_annotation ;
337
306
@@ -354,9 +323,8 @@ fn rewrite_outlives<'tcx>(
354
323
// needed for correctness, since an SCC upstream of another with
355
324
// a universe violation will "infect" its downstream SCCs to also
356
325
// outlive static.
357
- outlives_static. insert ( scc) ;
358
326
let scc_representative_outlives_static = OutlivesConstraint {
359
- sup : annotation. representative ,
327
+ sup : annotation. representative . rvid ( ) ,
360
328
sub : fr_static,
361
329
category : ConstraintCategory :: IllegalUniverse ,
362
330
locations : Locations :: All ( rustc_span:: DUMMY_SP ) ,
@@ -365,7 +333,9 @@ fn rewrite_outlives<'tcx>(
365
333
from_closure : false ,
366
334
} ;
367
335
outlives_constraints. push ( scc_representative_outlives_static) ;
336
+ added_constraints = true ;
337
+ debug ! ( "Added {:?}: 'static!" , annotation. representative. rvid( ) ) ;
368
338
}
369
339
}
370
- outlives_static
340
+ added_constraints
371
341
}
0 commit comments