@@ -76,7 +76,7 @@ pub struct RegionTracker {
76
76
max_universe_placeholder_reached : ReachablePlaceholder ,
77
77
78
78
/// The smallest universe index reachable form the nodes of this SCC.
79
- min_reachable_universe : UniverseIndex ,
79
+ min_reachable_universe : ( UniverseIndex , RegionVid ) ,
80
80
81
81
/// The representative Region Variable Id for this SCC. We prefer
82
82
/// placeholders over existentially quantified variables, otherwise
@@ -87,10 +87,10 @@ pub struct RegionTracker {
87
87
representative_origin : RepresentativeOrigin ,
88
88
89
89
/// The smallest reachable placeholder from this SCC (including in it).
90
- min_reachable_placeholder : Option < RegionVid > ,
90
+ pub ( crate ) min_reachable_placeholder : Option < RegionVid > ,
91
91
92
92
/// The largest reachable placeholder from this SCC (including in it).
93
- max_reachable_placeholder : Option < RegionVid > ,
93
+ pub ( crate ) max_reachable_placeholder : Option < RegionVid > ,
94
94
95
95
/// Is there at least one placeholder in this SCC?
96
96
contains_placeholder : bool ,
@@ -143,7 +143,7 @@ impl RegionTracker {
143
143
144
144
Self {
145
145
max_universe_placeholder_reached,
146
- min_reachable_universe : definition. universe ,
146
+ min_reachable_universe : ( definition. universe , rvid ) ,
147
147
representative : rvid,
148
148
representative_origin,
149
149
min_reachable_placeholder : representative_if_placeholder,
@@ -152,24 +152,6 @@ impl RegionTracker {
152
152
}
153
153
}
154
154
155
- /// Return true if this SCC contains a placeholder that
156
- /// reaches another placeholder, through other SCCs or within
157
- /// it.
158
- fn placeholder_reaches_placeholder ( & self ) -> bool {
159
- // If min and max are different then at least two placeholders
160
- // must be reachable from us. It remains to determine if and
161
- // whose problem that is.
162
- //
163
- // If we are not a placeholder
164
- // we are seeing upstream placeholders, which may be fine, or
165
- // if it is a problem it's the problem for other placeholders.
166
- //
167
- // If we *are* a placeholder, we are reaching at least one other
168
- // placeholder upstream.
169
- self . contains_placeholder
170
- && self . min_reachable_placeholder != self . max_reachable_placeholder
171
- }
172
-
173
155
/// If the representative is a placeholder, return it,
174
156
/// otherwise return None.
175
157
fn placeholder_representative ( & self ) -> Option < RegionVid > {
@@ -182,7 +164,7 @@ impl RegionTracker {
182
164
183
165
/// The smallest-indexed universe reachable from and/or in this SCC.
184
166
fn min_universe ( self ) -> UniverseIndex {
185
- self . min_reachable_universe
167
+ self . min_reachable_universe . 0
186
168
}
187
169
188
170
fn merge_reachable_placeholders ( & mut self , other : & Self ) {
@@ -216,58 +198,37 @@ impl RegionTracker {
216
198
std:: cmp:: min ( self . min_reachable_universe , other. min_reachable_universe ) ;
217
199
}
218
200
219
- /// Returns an offending region if the annotated SCC reaches a placeholder
220
- /// with a universe larger than the smallest reachable one,
221
- /// or if a placeholder reaches another placeholder, `None` otherwise.
222
- pub ( crate ) fn placeholder_violation (
223
- & self ,
224
- sccs : & Sccs < RegionVid , ConstraintSccIndex , Self > ,
225
- ) -> Option < RegionVid > {
226
- // Note: we arbitrarily prefer universe violations
227
- // to placeholder-reaches-placeholder violations.
228
- // violations.
229
-
230
- // Case 1: a universe violation
231
- if let ReachablePlaceholder :: Placeholder {
201
+ /// Figure out if there is a universe violation going on.
202
+ /// This can happen in two cases: either one of our placeholders
203
+ /// had its universe lowered from reaching a region with a lower universe,
204
+ /// (in which case we blame the lower universe's region), or because we reached
205
+ /// a larger universe (in which case we blame the larger universe's region).
206
+ pub ( crate ) fn universe_violation ( & self ) -> Option < RegionVid > {
207
+ let ReachablePlaceholder :: Placeholder {
232
208
universe : max_reached_universe,
233
- rvid : belonging_to_rvid ,
209
+ rvid : large_u_rvid ,
234
210
} = self . max_universe_placeholder_reached
235
- {
236
- if self . min_universe ( ) . cannot_name ( max_reached_universe) {
237
- return Some ( belonging_to_rvid) ;
238
- }
239
- }
240
-
241
- // Case 2: a placeholder (in our SCC) reaches another placeholder
242
- if self . placeholder_reaches_placeholder ( ) {
243
- // We know that this SCC contains at least one placeholder
244
- // and that at least two placeholders are reachable from
245
- // this SCC.
246
- //
247
- // We try to pick one that isn't in our SCC, if possible.
248
- // We *always* pick one that is not equal to the representative.
249
-
250
- // Unwrap safety: we know both these values are Some, since
251
- // there are two reachable placeholders at least.
252
- let min_reachable = self . min_reachable_placeholder . unwrap ( ) ;
211
+ else {
212
+ return None ;
213
+ } ;
253
214
254
- if sccs . scc ( min_reachable ) != sccs . scc ( self . representative ) {
255
- return Some ( min_reachable ) ;
256
- }
215
+ if ! self . min_universe ( ) . cannot_name ( max_reached_universe ) {
216
+ return None ;
217
+ } ;
257
218
258
- // Either the largest reachable placeholder is outside our SCC,
259
- // or we *must* blame a placeholder in our SCC since the violation
260
- // happens inside of it. It's slightly easier to always arbitrarily
261
- // pick the largest one, so we do. This also nicely guarantees that
262
- // we don't pick the representative, since the representative is the
263
- // smallest placeholder by index in the SCC if it is a placeholder
264
- // so in order for it to also be the largest reachable min would
265
- // have to be equal to max, but then we would only have reached one
266
- // placeholder .
267
- return Some ( self . max_reachable_placeholder . unwrap ( ) ) ;
268
- }
219
+ debug ! ( "Universe {max_reached_universe:?} is too large for its SCC!" ) ;
220
+ // We originally had a large enough universe to fit all our reachable
221
+ // placeholders, but had it lowered because we also reached something
222
+ // small-universed. In this case, that's to blame!
223
+ let to_blame = if self . representative == large_u_rvid {
224
+ debug ! ( "{:?} lowered our universe!" , self . min_reachable_universe ) ;
225
+ self . min_reachable_universe . 1
226
+ } else {
227
+ // The problem is that we, who have a small universe, reach a large one .
228
+ large_u_rvid
229
+ } ;
269
230
270
- None
231
+ Some ( to_blame )
271
232
}
272
233
}
273
234
@@ -1949,14 +1910,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1949
1910
// relation, redirect the search to the placeholder to blame.
1950
1911
if self . is_static ( to) {
1951
1912
for constraint in path. iter ( ) {
1952
- let ConstraintCategory :: IllegalPlaceholder ( culprit_r) = constraint. category else {
1913
+ let ConstraintCategory :: IllegalPlaceholder ( culprit_from, culprit_to) =
1914
+ constraint. category
1915
+ else {
1953
1916
continue ;
1954
1917
} ;
1955
1918
1956
- debug ! ( "{culprit_r :?} is the reason {from:?}: 'static!" ) ;
1919
+ debug ! ( "{culprit_from:?}: {culprit_to :?} is the reason {from:?}: 'static!" ) ;
1957
1920
// FIXME: think: this may be for transitive reasons and
1958
1921
// we may have to do this arbitrarily many times. Or may we?
1959
- return self . find_constraint_path_to ( from, |r| r == culprit_r, false ) . unwrap ( ) ;
1922
+ return self
1923
+ . find_constraint_path_to ( culprit_from, |r| r == culprit_to, false )
1924
+ . unwrap ( ) ;
1960
1925
}
1961
1926
}
1962
1927
// No funny business; just return the path!
0 commit comments