@@ -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 {
@@ -168,13 +179,13 @@ impl RegionTracker {
168
179
169
180
/// Determine if we can name all the placeholders in `other`.
170
181
pub ( crate ) fn can_name_all_placeholders ( & self , other : Self ) -> bool {
171
- other. reachable_placeholders . can_be_named_by ( self . max_nameable_universe . 0 )
182
+ other. reachable_placeholders . can_be_named_by ( self . min_max_nameable_universe )
172
183
}
173
184
174
185
/// If this SCC reaches a placeholder it can't name, return it.
175
186
fn unnameable_placeholder ( & self ) -> Option < ( UniverseIndex , RegionVid ) > {
176
187
self . reachable_placeholders . max_universe ( ) . filter ( |& ( placeholder_universe, _) | {
177
- !self . max_nameable_universe ( ) . can_name ( placeholder_universe)
188
+ !self . min_max_nameable_universe . can_name ( placeholder_universe)
178
189
} )
179
190
}
180
191
@@ -189,7 +200,12 @@ impl RegionTracker {
189
200
return None ;
190
201
} ;
191
202
192
- let ( reachable_lowest_max_u, reachable_lowest_max_u_rvid) = self . max_nameable_universe ;
203
+ let Some ( ( reachable_lowest_max_u, reachable_lowest_max_u_rvid) ) =
204
+ self . min_universe_existential
205
+ else {
206
+ debug ! ( "SCC universe wasn't lowered by an existential; skipping." ) ;
207
+ return None ;
208
+ } ;
193
209
194
210
( !self . reachable_placeholders . can_be_named_by ( reachable_lowest_max_u) )
195
211
. then_some ( reachable_lowest_max_u_rvid)
@@ -222,14 +238,20 @@ impl scc::Annotation for RegionTracker {
222
238
223
239
Self {
224
240
representative : self . representative . min ( other. representative ) ,
225
- max_nameable_universe : self . max_nameable_universe . min ( other. max_nameable_universe ) ,
226
- reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
241
+ ..self . merge_reached ( other)
227
242
}
228
243
}
229
244
245
+ #[ inline( always) ]
230
246
fn merge_reached ( self , other : Self ) -> Self {
231
247
Self {
232
- max_nameable_universe : self . max_nameable_universe . min ( other. max_nameable_universe ) ,
248
+ min_universe_existential : self
249
+ . min_universe_existential
250
+ . xor ( other. min_universe_existential )
251
+ . or_else ( || self . min_universe_existential . min ( other. min_universe_existential ) ) ,
252
+ min_max_nameable_universe : self
253
+ . min_max_nameable_universe
254
+ . min ( other. min_max_nameable_universe ) ,
233
255
reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
234
256
representative : self . representative ,
235
257
}
@@ -438,19 +460,7 @@ fn rewrite_placeholder_outlives<'tcx>(
438
460
variance_info : VarianceDiagInfo :: None ,
439
461
from_closure : false ,
440
462
} ) ;
441
- } else if !( annotation. reaches_existential_that_cannot_name_us ( ) . is_some ( )
442
- || annotation. reaches_other_placeholder ( annotation. representative . rvid ( ) ) . is_some ( ) )
443
- {
444
- // The SCC's representative is not nameable from some region
445
- // that ends up in the SCC. This means there is nothing for us to do.
446
- // However, this is only possible under circumstances that produce
447
- // errors, so we make sure that we catch them here. Otherwise,
448
- // there might actually be soundness issues!
449
- bug ! (
450
- "Universe of SCC {scc:?} should have been lowered by an existential or at least another placeholder but was lowered by {:?}, which is neither." ,
451
- annotation. max_nameable_universe
452
- ) ;
453
- } ;
463
+ }
454
464
}
455
465
added_constraints
456
466
}
@@ -482,12 +492,12 @@ fn find_placeholder_mismatch_errors<'tcx>(
482
492
let scc = sccs. scc ( rvid) ;
483
493
let annotation = annotations. scc_to_annotation [ scc] ;
484
494
485
- if let Some ( existential_that_cannot_name_rvid ) =
486
- annotation . reaches_existential_that_cannot_name_us ( )
487
- {
495
+ if let Some ( cannot_name_rvid ) = annotation . reaches_existential_that_cannot_name_us ( ) {
496
+ debug ! ( "Existential {cannot_name_rvid:?} lowered our universe..." ) ;
497
+
488
498
errors_buffer. push ( RegionErrorKind :: PlaceholderOutlivesExistentialThatCannotNameIt {
489
499
longer_fr : rvid,
490
- existential_that_cannot_name_longer : existential_that_cannot_name_rvid ,
500
+ existential_that_cannot_name_longer : cannot_name_rvid ,
491
501
placeholder : origin_a,
492
502
} )
493
503
}
0 commit comments