@@ -20,7 +20,7 @@ use crate::ty::VarianceDiagInfo;
20
20
use crate :: type_check:: free_region_relations:: UniversalRegionRelations ;
21
21
use crate :: type_check:: { Locations , MirTypeckRegionConstraints } ;
22
22
use crate :: universal_regions:: UniversalRegions ;
23
- use crate :: { BorrowckInferCtxt , NllRegionVariableOrigin , bug } ;
23
+ use crate :: { BorrowckInferCtxt , NllRegionVariableOrigin } ;
24
24
25
25
/// A set of outlives constraints after rewriting to remove
26
26
/// higher-kinded constraints.
@@ -122,10 +122,12 @@ impl PlaceholderReachability {
122
122
pub ( crate ) struct RegionTracker {
123
123
reachable_placeholders : PlaceholderReachability ,
124
124
125
- /// The largest universe nameable from this SCC.
126
- /// It is the smallest nameable universes of all
127
- /// existential regions reachable from it. Small Rvids are preferred.
128
- max_nameable_universe : ( UniverseIndex , RegionVid ) ,
125
+ /// The smallest max nameable universe of all
126
+ /// regions reachable from this SCC.
127
+ min_max_nameable_universe : UniverseIndex ,
128
+
129
+ /// The existential region with the smallest universe, if any.
130
+ min_universe_existential : Option < ( UniverseIndex , RegionVid ) > ,
129
131
130
132
/// The representative Region Variable Id for this SCC.
131
133
pub ( crate ) representative : Representative ,
@@ -146,7 +148,15 @@ impl RegionTracker {
146
148
147
149
Self {
148
150
reachable_placeholders,
149
- max_nameable_universe : ( definition. universe , rvid) ,
151
+ min_universe_existential : if matches ! (
152
+ definition. origin,
153
+ NllRegionVariableOrigin :: Existential { .. }
154
+ ) {
155
+ Some ( ( definition. universe , rvid) )
156
+ } else {
157
+ None
158
+ } ,
159
+ min_max_nameable_universe : definition. universe ,
150
160
representative : Representative :: new ( rvid, definition) ,
151
161
}
152
162
}
@@ -155,7 +165,8 @@ impl RegionTracker {
155
165
/// largest nameable universe of any reachable region, or
156
166
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
157
167
pub ( crate ) fn max_nameable_universe ( self ) -> UniverseIndex {
158
- self . max_nameable_universe . 0
168
+ // Note that this is stricter than it might need to be!
169
+ self . min_max_nameable_universe
159
170
}
160
171
161
172
pub ( crate ) fn max_placeholder_universe_reached ( self ) -> UniverseIndex {
@@ -166,19 +177,19 @@ impl RegionTracker {
166
177
}
167
178
}
168
179
169
- /// Determine if the tracked universes of the two SCCs are compatible.
180
+ /// Determine if the universe constraints of the members of two SCCs are compatible.
170
181
pub ( crate ) fn universe_compatible_with ( & self , other : Self ) -> bool {
171
182
// HACK: We first check whether we can name the highest existential universe
172
183
// of `other`. This only exists to avoid errors in case that scc already
173
184
// depends on a placeholder it cannot name itself.
174
- self . max_nameable_universe ( ) . can_name ( other. max_nameable_universe ( ) )
175
- || other. reachable_placeholders . can_be_named_by ( self . max_nameable_universe ( ) )
185
+ self . min_max_nameable_universe . can_name ( other. min_max_nameable_universe )
186
+ || other. reachable_placeholders . can_be_named_by ( self . min_max_nameable_universe )
176
187
}
177
188
178
189
/// If this SCC reaches a placeholder it can't name, return it.
179
190
fn unnameable_placeholder ( & self ) -> Option < ( UniverseIndex , RegionVid ) > {
180
191
self . reachable_placeholders . max_universe ( ) . filter ( |& ( placeholder_universe, _) | {
181
- !self . max_nameable_universe ( ) . can_name ( placeholder_universe)
192
+ !self . min_max_nameable_universe . can_name ( placeholder_universe)
182
193
} )
183
194
}
184
195
@@ -193,7 +204,12 @@ impl RegionTracker {
193
204
return None ;
194
205
} ;
195
206
196
- let ( reachable_lowest_max_u, reachable_lowest_max_u_rvid) = self . max_nameable_universe ;
207
+ let Some ( ( reachable_lowest_max_u, reachable_lowest_max_u_rvid) ) =
208
+ self . min_universe_existential
209
+ else {
210
+ debug ! ( "SCC universe wasn't lowered by an existential; skipping." ) ;
211
+ return None ;
212
+ } ;
197
213
198
214
( !self . reachable_placeholders . can_be_named_by ( reachable_lowest_max_u) )
199
215
. then_some ( reachable_lowest_max_u_rvid)
@@ -226,14 +242,20 @@ impl scc::Annotation for RegionTracker {
226
242
227
243
Self {
228
244
representative : self . representative . min ( other. representative ) ,
229
- max_nameable_universe : self . max_nameable_universe . min ( other. max_nameable_universe ) ,
230
- reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
245
+ ..self . merge_reached ( other)
231
246
}
232
247
}
233
248
249
+ #[ inline( always) ]
234
250
fn merge_reached ( self , other : Self ) -> Self {
235
251
Self {
236
- max_nameable_universe : self . max_nameable_universe . min ( other. max_nameable_universe ) ,
252
+ min_universe_existential : self
253
+ . min_universe_existential
254
+ . xor ( other. min_universe_existential )
255
+ . or_else ( || self . min_universe_existential . min ( other. min_universe_existential ) ) ,
256
+ min_max_nameable_universe : self
257
+ . min_max_nameable_universe
258
+ . min ( other. min_max_nameable_universe ) ,
237
259
reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
238
260
representative : self . representative ,
239
261
}
@@ -442,19 +464,7 @@ fn rewrite_placeholder_outlives<'tcx>(
442
464
variance_info : VarianceDiagInfo :: None ,
443
465
from_closure : false ,
444
466
} ) ;
445
- } else if !( annotation. reaches_existential_that_cannot_name_us ( ) . is_some ( )
446
- || annotation. reaches_other_placeholder ( annotation. representative . rvid ( ) ) . is_some ( ) )
447
- {
448
- // The SCC's representative is not nameable from some region
449
- // that ends up in the SCC. This means there is nothing for us to do.
450
- // However, this is only possible under circumstances that produce
451
- // errors, so we make sure that we catch them here. Otherwise,
452
- // there might actually be soundness issues!
453
- bug ! (
454
- "Universe of SCC {scc:?} should have been lowered by an existential or at least another placeholder but was lowered by {:?}, which is neither." ,
455
- annotation. max_nameable_universe
456
- ) ;
457
- } ;
467
+ }
458
468
}
459
469
added_constraints
460
470
}
@@ -486,12 +496,12 @@ fn find_placeholder_mismatch_errors<'tcx>(
486
496
let scc = sccs. scc ( rvid) ;
487
497
let annotation = annotations. scc_to_annotation [ scc] ;
488
498
489
- if let Some ( existential_that_cannot_name_rvid ) =
490
- annotation . reaches_existential_that_cannot_name_us ( )
491
- {
499
+ if let Some ( cannot_name_rvid ) = annotation . reaches_existential_that_cannot_name_us ( ) {
500
+ debug ! ( "Existential {cannot_name_rvid:?} lowered our universe..." ) ;
501
+
492
502
errors_buffer. push ( RegionErrorKind :: PlaceholderOutlivesExistentialThatCannotNameIt {
493
503
longer_fr : rvid,
494
- existential_that_cannot_name_longer : existential_that_cannot_name_rvid ,
504
+ existential_that_cannot_name_longer : cannot_name_rvid ,
495
505
placeholder : origin_a,
496
506
} )
497
507
}
0 commit comments