@@ -20,7 +20,7 @@ use crate::ty::VarianceDiagInfo;
2020use crate :: type_check:: free_region_relations:: UniversalRegionRelations ;
2121use crate :: type_check:: { Locations , MirTypeckRegionConstraints } ;
2222use crate :: universal_regions:: UniversalRegions ;
23- use crate :: { BorrowckInferCtxt , NllRegionVariableOrigin , bug } ;
23+ use crate :: { BorrowckInferCtxt , NllRegionVariableOrigin } ;
2424
2525/// A set of outlives constraints after rewriting to remove
2626/// higher-kinded constraints.
@@ -122,10 +122,12 @@ impl PlaceholderReachability {
122122pub ( crate ) struct RegionTracker {
123123 reachable_placeholders : PlaceholderReachability ,
124124
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 ) > ,
129131
130132 /// The representative Region Variable Id for this SCC.
131133 pub ( crate ) representative : Representative ,
@@ -146,7 +148,15 @@ impl RegionTracker {
146148
147149 Self {
148150 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 ,
150160 representative : Representative :: new ( rvid, definition) ,
151161 }
152162 }
@@ -155,7 +165,8 @@ impl RegionTracker {
155165 /// largest nameable universe of any reachable region, or
156166 /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
157167 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
159170 }
160171
161172 pub ( crate ) fn max_placeholder_universe_reached ( self ) -> UniverseIndex {
@@ -168,13 +179,13 @@ impl RegionTracker {
168179
169180 /// Determine if we can name all the placeholders in `other`.
170181 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 )
172183 }
173184
174185 /// If this SCC reaches a placeholder it can't name, return it.
175186 fn unnameable_placeholder ( & self ) -> Option < ( UniverseIndex , RegionVid ) > {
176187 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)
178189 } )
179190 }
180191
@@ -189,7 +200,12 @@ impl RegionTracker {
189200 return None ;
190201 } ;
191202
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+ } ;
193209
194210 ( !self . reachable_placeholders . can_be_named_by ( reachable_lowest_max_u) )
195211 . then_some ( reachable_lowest_max_u_rvid)
@@ -222,14 +238,20 @@ impl scc::Annotation for RegionTracker {
222238
223239 Self {
224240 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)
227242 }
228243 }
229244
245+ #[ inline( always) ]
230246 fn merge_reached ( self , other : Self ) -> Self {
231247 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 ) ,
233255 reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
234256 representative : self . representative ,
235257 }
@@ -438,19 +460,7 @@ pub(crate) fn rewrite_placeholder_outlives<'tcx>(
438460 variance_info : VarianceDiagInfo :: None ,
439461 from_closure : false ,
440462 } ) ;
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+ }
454464 }
455465 added_constraints
456466}
@@ -482,12 +492,12 @@ fn find_placeholder_mismatch_errors<'tcx>(
482492 let scc = sccs. scc ( rvid) ;
483493 let annotation = annotations. scc_to_annotation [ scc] ;
484494
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+
488498 errors_buffer. push ( RegionErrorKind :: PlaceholderOutlivesExistentialThatCannotNameIt {
489499 longer_fr : rvid,
490- existential_that_cannot_name_longer : existential_that_cannot_name_rvid ,
500+ existential_that_cannot_name_longer : cannot_name_rvid ,
491501 placeholder : origin_a,
492502 } )
493503 }
0 commit comments