@@ -75,7 +75,7 @@ pub struct RegionTracker {
7575 max_universe_placeholder_reached : ReachablePlaceholder ,
7676
7777 /// The smallest universe index reachable form the nodes of this SCC.
78- min_reachable_universe : UniverseIndex ,
78+ min_reachable_universe : ( UniverseIndex , RegionVid ) ,
7979
8080 /// The representative Region Variable Id for this SCC. We prefer
8181 /// placeholders over existentially quantified variables, otherwise
@@ -86,10 +86,10 @@ pub struct RegionTracker {
8686 representative_origin : RepresentativeOrigin ,
8787
8888 /// The smallest reachable placeholder from this SCC (including in it).
89- min_reachable_placeholder : Option < RegionVid > ,
89+ pub ( crate ) min_reachable_placeholder : Option < RegionVid > ,
9090
9191 /// The largest reachable placeholder from this SCC (including in it).
92- max_reachable_placeholder : Option < RegionVid > ,
92+ pub ( crate ) max_reachable_placeholder : Option < RegionVid > ,
9393
9494 /// Is there at least one placeholder in this SCC?
9595 contains_placeholder : bool ,
@@ -142,7 +142,7 @@ impl RegionTracker {
142142
143143 Self {
144144 max_universe_placeholder_reached,
145- min_reachable_universe : definition. universe ,
145+ min_reachable_universe : ( definition. universe , rvid ) ,
146146 representative : rvid,
147147 representative_origin,
148148 min_reachable_placeholder : representative_if_placeholder,
@@ -151,24 +151,6 @@ impl RegionTracker {
151151 }
152152 }
153153
154- /// Return true if this SCC contains a placeholder that
155- /// reaches another placeholder, through other SCCs or within
156- /// it.
157- fn placeholder_reaches_placeholder ( & self ) -> bool {
158- // If min and max are different then at least two placeholders
159- // must be reachable from us. It remains to determine if and
160- // whose problem that is.
161- //
162- // If we are not a placeholder
163- // we are seeing upstream placeholders, which may be fine, or
164- // if it is a problem it's the problem for other placeholders.
165- //
166- // If we *are* a placeholder, we are reaching at least one other
167- // placeholder upstream.
168- self . contains_placeholder
169- && self . min_reachable_placeholder != self . max_reachable_placeholder
170- }
171-
172154 /// If the representative is a placeholder, return it,
173155 /// otherwise return None.
174156 fn placeholder_representative ( & self ) -> Option < RegionVid > {
@@ -181,7 +163,7 @@ impl RegionTracker {
181163
182164 /// The smallest-indexed universe reachable from and/or in this SCC.
183165 fn min_universe ( self ) -> UniverseIndex {
184- self . min_reachable_universe
166+ self . min_reachable_universe . 0
185167 }
186168
187169 fn merge_reachable_placeholders ( & mut self , other : & Self ) {
@@ -215,58 +197,37 @@ impl RegionTracker {
215197 std:: cmp:: min ( self . min_reachable_universe , other. min_reachable_universe ) ;
216198 }
217199
218- /// Returns an offending region if the annotated SCC reaches a placeholder
219- /// with a universe larger than the smallest reachable one,
220- /// or if a placeholder reaches another placeholder, `None` otherwise.
221- pub ( crate ) fn placeholder_violation (
222- & self ,
223- sccs : & Sccs < RegionVid , ConstraintSccIndex , Self > ,
224- ) -> Option < RegionVid > {
225- // Note: we arbitrarily prefer universe violations
226- // to placeholder-reaches-placeholder violations.
227- // violations.
228-
229- // Case 1: a universe violation
230- if let ReachablePlaceholder :: Placeholder {
200+ /// Figure out if there is a universe violation going on.
201+ /// This can happen in two cases: either one of our placeholders
202+ /// had its universe lowered from reaching a region with a lower universe,
203+ /// (in which case we blame the lower universe's region), or because we reached
204+ /// a larger universe (in which case we blame the larger universe's region).
205+ pub ( crate ) fn universe_violation ( & self ) -> Option < RegionVid > {
206+ let ReachablePlaceholder :: Placeholder {
231207 universe : max_reached_universe,
232- rvid : belonging_to_rvid ,
208+ rvid : large_u_rvid ,
233209 } = self . max_universe_placeholder_reached
234- {
235- if self . min_universe ( ) . cannot_name ( max_reached_universe) {
236- return Some ( belonging_to_rvid) ;
237- }
238- }
239-
240- // Case 2: a placeholder (in our SCC) reaches another placeholder
241- if self . placeholder_reaches_placeholder ( ) {
242- // We know that this SCC contains at least one placeholder
243- // and that at least two placeholders are reachable from
244- // this SCC.
245- //
246- // We try to pick one that isn't in our SCC, if possible.
247- // We *always* pick one that is not equal to the representative.
248-
249- // Unwrap safety: we know both these values are Some, since
250- // there are two reachable placeholders at least.
251- let min_reachable = self . min_reachable_placeholder . unwrap ( ) ;
210+ else {
211+ return None ;
212+ } ;
252213
253- if sccs . scc ( min_reachable ) != sccs . scc ( self . representative ) {
254- return Some ( min_reachable ) ;
255- }
214+ if ! self . min_universe ( ) . cannot_name ( max_reached_universe ) {
215+ return None ;
216+ } ;
256217
257- // Either the largest reachable placeholder is outside our SCC,
258- // or we *must* blame a placeholder in our SCC since the violation
259- // happens inside of it. It's slightly easier to always arbitrarily
260- // pick the largest one, so we do. This also nicely guarantees that
261- // we don't pick the representative, since the representative is the
262- // smallest placeholder by index in the SCC if it is a placeholder
263- // so in order for it to also be the largest reachable min would
264- // have to be equal to max, but then we would only have reached one
265- // placeholder .
266- return Some ( self . max_reachable_placeholder . unwrap ( ) ) ;
267- }
218+ debug ! ( "Universe {max_reached_universe:?} is too large for its SCC!" ) ;
219+ // We originally had a large enough universe to fit all our reachable
220+ // placeholders, but had it lowered because we also reached something
221+ // small-universed. In this case, that's to blame!
222+ let to_blame = if self . representative == large_u_rvid {
223+ debug ! ( "{:?} lowered our universe!" , self . min_reachable_universe ) ;
224+ self . min_reachable_universe . 1
225+ } else {
226+ // The problem is that we, who have a small universe, reach a large one .
227+ large_u_rvid
228+ } ;
268229
269- None
230+ Some ( to_blame )
270231 }
271232}
272233
@@ -1948,14 +1909,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
19481909 // relation, redirect the search to the placeholder to blame.
19491910 if self . is_static ( to) {
19501911 for constraint in path. iter ( ) {
1951- let ConstraintCategory :: IllegalPlaceholder ( culprit_r) = constraint. category else {
1912+ let ConstraintCategory :: IllegalPlaceholder ( culprit_from, culprit_to) =
1913+ constraint. category
1914+ else {
19521915 continue ;
19531916 } ;
19541917
1955- debug ! ( "{culprit_r :?} is the reason {from:?}: 'static!" ) ;
1918+ debug ! ( "{culprit_from:?}: {culprit_to :?} is the reason {from:?}: 'static!" ) ;
19561919 // FIXME: think: this may be for transitive reasons and
19571920 // we may have to do this arbitrarily many times. Or may we?
1958- return self . find_constraint_path_to ( from, |r| r == culprit_r, false ) . unwrap ( ) ;
1921+ return self
1922+ . find_constraint_path_to ( culprit_from, |r| r == culprit_to, false )
1923+ . unwrap ( ) ;
19591924 }
19601925 }
19611926 // No funny business; just return the path!
0 commit comments