@@ -125,8 +125,11 @@ impl PlaceholderReachability {
125125/// the values of its elements. This annotates a single SCC.
126126#[ derive( Copy , Debug , Clone ) ]
127127pub ( crate ) struct RegionTracker {
128- /// The smallest universe reachable (and its region)
129- min_universe : ( UniverseIndex , RegionVid ) ,
128+ /// The smallest maximum universe reachable (and its region).
129+ /// This determines the largest nameable universe from this
130+ /// SCC. Earlier regions in the constraint graph are
131+ /// preferred.
132+ min_max_universe_reached : ( UniverseIndex , RegionVid ) ,
130133
131134 /// Metadata about reachable placeholders
132135 reachable_placeholders : PlaceholderReachability ,
@@ -149,27 +152,32 @@ impl RegionTracker {
149152 } ;
150153
151154 Self {
152- min_universe : ( definition. universe , rvid) ,
155+ // The largest reachable universe from a rvid is its
156+ // declared largest reachable one.
157+ min_max_universe_reached : ( definition. universe , rvid) ,
153158 reachable_placeholders,
154159 representative : Representative :: new ( rvid, definition) ,
155160 }
156161 }
157162
158- /// The smallest-indexed universe reachable from and/or in this SCC.
159- pub ( crate ) fn min_universe ( self ) -> UniverseIndex {
160- self . min_universe . 0
163+ /// The largest universe that can be named from this SCC is the
164+ /// smallest largest nameable universe of anything it reaches in
165+ /// the region constraint graph, or equivalently in logic terms:
166+ /// `max_u(scc) = min(max_u(r) for r in scc: r )`.
167+ pub ( crate ) fn max_nameable_universe ( self ) -> UniverseIndex {
168+ self . min_max_universe_reached . 0
161169 }
162170
163171 /// Determine if the tracked universes of the two SCCs
164172 /// are compatible.
165173 pub ( crate ) fn universe_compatible_with ( & self , other : Self ) -> bool {
166- self . min_universe ( ) . can_name ( other. min_universe ( ) )
167- || other. reachable_placeholders . can_be_named_by ( self . min_universe ( ) )
174+ self . max_nameable_universe ( ) . can_name ( other. max_nameable_universe ( ) )
175+ || other. reachable_placeholders . can_be_named_by ( self . max_nameable_universe ( ) )
168176 }
169177
170178 /// If this SCC reaches an universe that's too large, return it.
171179 fn reaches_too_large_universe ( & self ) -> Option < ( RegionVid , UniverseIndex ) > {
172- let min_u = self . min_universe ( ) ;
180+ let min_u = self . max_nameable_universe ( ) ;
173181
174182 let PlaceholderReachability :: Placeholders { max_universe : ( max_u, max_u_rvid) , .. } =
175183 self . reachable_placeholders
@@ -185,28 +193,31 @@ impl RegionTracker {
185193 }
186194}
187195
196+ /// Pick the smallest universe index out of two, preferring
197+ /// the first argument if they are equal.
198+ #[ inline( always) ]
199+ fn pick_min_max_universe ( a : RegionTracker , b : RegionTracker ) -> ( UniverseIndex , RegionVid ) {
200+ std:: cmp:: min_by_key (
201+ a. min_max_universe_reached ,
202+ b. min_max_universe_reached ,
203+ |x : & ( UniverseIndex , RegionVid ) | x. 0 ,
204+ )
205+ }
206+
188207impl scc:: Annotation for RegionTracker {
189208 fn merge_scc ( self , other : Self ) -> Self {
190209 trace ! ( "{:?} << {:?}" , self . representative, other. representative) ;
191210
192211 Self {
193212 reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
194- min_universe : std:: cmp:: min_by_key (
195- self . min_universe ,
196- other. min_universe ,
197- |x : & ( UniverseIndex , RegionVid ) | x. 0 ,
198- ) ,
213+ min_max_universe_reached : pick_min_max_universe ( self , other) ,
199214 representative : self . representative . merge_scc ( other. representative ) ,
200215 }
201216 }
202217
203218 fn merge_reached ( mut self , other : Self ) -> Self {
204219 let already_has_placeholder_violation = self . reaches_too_large_universe ( ) . is_some ( ) ;
205- self . min_universe = std:: cmp:: min_by_key (
206- self . min_universe ,
207- other. min_universe ,
208- |x : & ( UniverseIndex , RegionVid ) | x. 0 ,
209- ) ;
220+ self . min_max_universe_reached = pick_min_max_universe ( self , other) ;
210221 // This detail is subtle. We stop early here, because there may be multiple
211222 // illegally reached regions, but they are not equally good as blame candidates.
212223 // In general, the ones with the smallest indices of their RegionVids will
@@ -421,15 +432,15 @@ fn rewrite_outlives<'tcx>(
421432 continue ;
422433 } ;
423434
424- let min_u = annotation. min_universe ( ) ;
435+ let min_u = annotation. max_nameable_universe ( ) ;
425436
426437 debug ! (
427438 "Universe {max_u:?} is too large for its SCC, represented by {:?}" ,
428439 annotation. representative
429440 ) ;
430441 let blame_to = if annotation. representative . rvid ( ) == max_u_rvid {
431442 // We originally had a large enough universe to fit all our reachable
432- // placeholders, but had it lowered because we also absorbed something
443+ // placeholders, but had it lowered because we also reached something
433444 // small-universed. In this case, that's to blame!
434445 let small_universed_rvid = find_region (
435446 outlives_constraints,
0 commit comments