@@ -115,6 +115,72 @@ impl PlaceholderReachability {
115115 }
116116}
117117
118+ #[ derive( Copy , Debug , Clone ) ]
119+
120+ enum PlaceholderConstraints {
121+ /// The SCC must be able to name this placeholder, in the SCC.
122+ Name ( UniverseIndex ) ,
123+ /// Any placeholder we reach must be nameable from this existential.
124+ NameableBy ( RegionVid , UniverseIndex ) ,
125+ /// Both constraints at the same time.
126+ NameAndBeNamed { name : UniverseIndex , nameable_by : ( RegionVid , UniverseIndex ) } ,
127+ }
128+
129+ impl PlaceholderConstraints {
130+ fn add_name ( self , name : UniverseIndex ) -> Self {
131+ use PlaceholderConstraints :: * ;
132+
133+ match self {
134+ Name ( universe_index) => Name ( universe_index. min ( name) ) ,
135+ NameableBy ( nb_rvid, nb_u) => NameAndBeNamed { name, nameable_by : ( nb_rvid, nb_u) } ,
136+ NameAndBeNamed { name : my_name, nameable_by } => {
137+ NameAndBeNamed { name : my_name. min ( name) , nameable_by }
138+ }
139+ }
140+ }
141+
142+ fn add_nameable_by ( self , region_vid : RegionVid , universe : UniverseIndex ) -> Self {
143+ use PlaceholderConstraints :: * ;
144+
145+ match self {
146+ Name ( universe_index) => {
147+ NameAndBeNamed { name : universe_index, nameable_by : ( region_vid, universe) }
148+ }
149+ NameableBy ( my_rvid, my_universe_index) => {
150+ let ( u, rvid) = ( ( my_universe_index, my_rvid) ) . min ( ( universe, region_vid) ) ;
151+ NameableBy ( rvid, u)
152+ }
153+ NameAndBeNamed { name, nameable_by } => {
154+ let ( u, rvid) = ( ( nameable_by. 1 , nameable_by. 0 ) ) . min ( ( universe, region_vid) ) ;
155+ NameAndBeNamed { name, nameable_by : ( rvid, u) }
156+ }
157+ }
158+ }
159+
160+ fn merge_scc ( self , other : Self ) -> Self {
161+ use PlaceholderConstraints :: * ;
162+ match other {
163+ Name ( universe_index) | NameAndBeNamed { name : universe_index, .. } => {
164+ self . add_name ( universe_index)
165+ }
166+ _ => self ,
167+ }
168+ . merge_reached ( other)
169+ }
170+
171+ #[ inline( always) ]
172+ fn merge_reached ( self , reached : Self ) -> Self {
173+ use PlaceholderConstraints :: * ;
174+ match reached {
175+ Name ( _) => self ,
176+ NameableBy ( region_vid, universe_index)
177+ | NameAndBeNamed { nameable_by : ( region_vid, universe_index) , .. } => {
178+ self . add_nameable_by ( region_vid, universe_index)
179+ }
180+ }
181+ }
182+ }
183+
118184/// An annotation for region graph SCCs that tracks
119185/// the values of its elements. This annotates a single SCC.
120186#[ derive( Copy , Debug , Clone ) ]
@@ -125,14 +191,8 @@ pub(crate) struct RegionTracker {
125191 /// regions reachable from this SCC.
126192 min_max_nameable_universe : UniverseIndex ,
127193
128- /// The largest universe of a placeholder in this SCC. Iff
129- /// an existential can name this universe it's allowed to
130- /// reach us.
131- scc_placeholder_largest_universe : Option < UniverseIndex > ,
132-
133- /// The reached existential region with the smallest universe, if any. This
134- /// is an upper bound on the universe.
135- min_universe_existential : Option < ( UniverseIndex , RegionVid ) > ,
194+ /// State tracking for exceptional circumstances.
195+ exception : Option < PlaceholderConstraints > ,
136196
137197 /// The representative Region Variable Id for this SCC.
138198 pub ( crate ) representative : Representative ,
@@ -141,6 +201,7 @@ pub(crate) struct RegionTracker {
141201impl RegionTracker {
142202 pub ( crate ) fn new ( rvid : RegionVid , definition : & RegionDefinition < ' _ > ) -> Self {
143203 use NllRegionVariableOrigin :: * ;
204+ use PlaceholderConstraints :: * ;
144205 use PlaceholderReachability :: * ;
145206
146207 let min_max_nameable_universe = definition. universe ;
@@ -151,8 +212,7 @@ impl RegionTracker {
151212 FreeRegion => Self {
152213 reachable_placeholders : NoPlaceholders ,
153214 min_max_nameable_universe,
154- scc_placeholder_largest_universe : None ,
155- min_universe_existential : None ,
215+ exception : None ,
156216 representative,
157217 } ,
158218 Placeholder ( _) => Self {
@@ -162,15 +222,13 @@ impl RegionTracker {
162222 max_placeholder : rvid,
163223 } ,
164224 min_max_nameable_universe,
165- scc_placeholder_largest_universe : Some ( definition. universe ) ,
166- min_universe_existential : None ,
225+ exception : Some ( Name ( definition. universe ) ) ,
167226 representative,
168227 } ,
169228 Existential { .. } => Self {
170229 reachable_placeholders : NoPlaceholders ,
171230 min_max_nameable_universe,
172- scc_placeholder_largest_universe : None ,
173- min_universe_existential : Some ( universe_and_rvid) ,
231+ exception : Some ( NameableBy ( rvid, definition. universe ) ) ,
174232 representative,
175233 } ,
176234 }
@@ -211,18 +269,16 @@ impl RegionTracker {
211269 ///
212270 /// Returns *a* culprit (there may be more than one).
213271 fn reaches_existential_that_cannot_name_us ( & self ) -> Option < RegionVid > {
214- let Some ( required_universe) = self . scc_placeholder_largest_universe else {
215- return None ;
216- } ;
217-
218- let Some ( ( reachable_lowest_max_u, reachable_lowest_max_u_rvid) ) =
219- self . min_universe_existential
220- else {
221- debug ! ( "SCC universe wasn't lowered by an existential; skipping." ) ;
222- return None ;
223- } ;
224-
225- ( !reachable_lowest_max_u. can_name ( required_universe) ) . then_some ( reachable_lowest_max_u_rvid)
272+ if let Some ( PlaceholderConstraints :: NameAndBeNamed {
273+ name : p_u,
274+ nameable_by : ( ex_rv, ex_u) ,
275+ } ) = self . exception
276+ && ex_u. cannot_name ( p_u)
277+ {
278+ Some ( ex_rv)
279+ } else {
280+ None
281+ }
226282 }
227283
228284 /// Determine if this SCC reaches a placeholder that isn't `placeholder_rvid`,
@@ -262,26 +318,33 @@ impl scc::Annotation for RegionTracker {
262318
263319 Self {
264320 representative : self . representative . min ( other. representative ) ,
265- scc_placeholder_largest_universe : self
266- . scc_placeholder_largest_universe
267- . max ( other. scc_placeholder_largest_universe ) ,
321+ exception : match ( self . exception , other. exception ) {
322+ ( None , other) | ( other, None ) => other,
323+ ( Some ( ours) , Some ( theirs) ) => Some ( ours. merge_scc ( theirs) ) ,
324+ } ,
268325 ..self . merge_reached ( other)
269326 }
270327 }
271328
272329 #[ inline( always) ]
273330 fn merge_reached ( self , other : Self ) -> Self {
331+ use PlaceholderConstraints :: * ;
274332 Self {
275- min_universe_existential : self
276- . min_universe_existential
277- . xor ( other. min_universe_existential )
278- . or_else ( || self . min_universe_existential . min ( other. min_universe_existential ) ) ,
333+ exception : match ( self . exception , other. exception ) {
334+ // Propagate only reachability (nameable by).
335+ ( None , None ) => None ,
336+ ( None , Some ( NameableBy ( r, u) ) )
337+ | ( None , Some ( NameAndBeNamed { nameable_by : ( r, u) , .. } ) ) => {
338+ Some ( NameableBy ( r, u) )
339+ }
340+ ( Some ( _) , None ) | ( None , Some ( Name ( _) ) ) => self . exception ,
341+ ( Some ( this) , Some ( that) ) => Some ( this. merge_reached ( that) ) ,
342+ } ,
279343 min_max_nameable_universe : self
280344 . min_max_nameable_universe
281345 . min ( other. min_max_nameable_universe ) ,
282346 reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
283347 representative : self . representative ,
284- scc_placeholder_largest_universe : self . scc_placeholder_largest_universe ,
285348 }
286349 }
287350}
@@ -363,7 +426,7 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
363426 mut outlives_constraints,
364427 universe_causes,
365428 type_tests,
366- placeholder_to_region : _
429+ placeholder_to_region : _,
367430 } = constraints;
368431
369432 let fr_static = universal_regions. fr_static ;
0 commit comments