@@ -125,8 +125,11 @@ impl PlaceholderReachability {
125
125
/// the values of its elements. This annotates a single SCC.
126
126
#[ derive( Copy , Debug , Clone ) ]
127
127
pub ( 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 ) ,
130
133
131
134
/// Metadata about reachable placeholders
132
135
reachable_placeholders : PlaceholderReachability ,
@@ -149,27 +152,32 @@ impl RegionTracker {
149
152
} ;
150
153
151
154
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) ,
153
158
reachable_placeholders,
154
159
representative : Representative :: new ( rvid, definition) ,
155
160
}
156
161
}
157
162
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
161
169
}
162
170
163
171
/// Determine if the tracked universes of the two SCCs
164
172
/// are compatible.
165
173
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 ( ) )
168
176
}
169
177
170
178
/// If this SCC reaches an universe that's too large, return it.
171
179
fn reaches_too_large_universe ( & self ) -> Option < ( RegionVid , UniverseIndex ) > {
172
- let min_u = self . min_universe ( ) ;
180
+ let min_u = self . max_nameable_universe ( ) ;
173
181
174
182
let PlaceholderReachability :: Placeholders { max_universe : ( max_u, max_u_rvid) , .. } =
175
183
self . reachable_placeholders
@@ -185,28 +193,31 @@ impl RegionTracker {
185
193
}
186
194
}
187
195
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
+
188
207
impl scc:: Annotation for RegionTracker {
189
208
fn merge_scc ( self , other : Self ) -> Self {
190
209
trace ! ( "{:?} << {:?}" , self . representative, other. representative) ;
191
210
192
211
Self {
193
212
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) ,
199
214
representative : self . representative . merge_scc ( other. representative ) ,
200
215
}
201
216
}
202
217
203
218
fn merge_reached ( mut self , other : Self ) -> Self {
204
219
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) ;
210
221
// This detail is subtle. We stop early here, because there may be multiple
211
222
// illegally reached regions, but they are not equally good as blame candidates.
212
223
// In general, the ones with the smallest indices of their RegionVids will
@@ -421,15 +432,15 @@ fn rewrite_outlives<'tcx>(
421
432
continue ;
422
433
} ;
423
434
424
- let min_u = annotation. min_universe ( ) ;
435
+ let min_u = annotation. max_nameable_universe ( ) ;
425
436
426
437
debug ! (
427
438
"Universe {max_u:?} is too large for its SCC, represented by {:?}" ,
428
439
annotation. representative
429
440
) ;
430
441
let blame_to = if annotation. representative . rvid ( ) == max_u_rvid {
431
442
// 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
433
444
// small-universed. In this case, that's to blame!
434
445
let small_universed_rvid = find_region (
435
446
outlives_constraints,
0 commit comments