@@ -157,7 +157,42 @@ impl<'tcx> RegionInferenceContext<'tcx> {
157
157
let target_scc = self . constraint_sccs . scc ( target_region) ;
158
158
let mut range = 0 ..path. len ( ) ;
159
159
160
- let should_reverse = match from_region_origin {
160
+ // As noted above, when reporting an error, there is typically a chain of constraints
161
+ // leading from some "source" region which must outlive some "target" region.
162
+ // In most cases, we prefer to "blame" the constraints closer to the target --
163
+ // but there is one exception. When constraints arise from higher-ranked subtyping,
164
+ // we generally prefer to blame the source value,
165
+ // as the "target" in this case tends to be some type annotation that the user gave.
166
+ // Therefore, if we find that the region origin is some instantiation
167
+ // of a higher-ranked region, we start our search from the "source" point
168
+ // rather than the "target", and we also tweak a few other things.
169
+ //
170
+ // An example might be this bit of Rust code:
171
+ //
172
+ // ```rust
173
+ // let x: fn(&'static ()) = |_| {};
174
+ // let y: for<'a> fn(&'a ()) = x;
175
+ // ```
176
+ //
177
+ // In MIR, this will be converted into a combination of assignments and type ascriptions.
178
+ // In particular, the 'static is imposed through a type ascription:
179
+ //
180
+ // ```rust
181
+ // x = ...;
182
+ // AscribeUserType(x, fn(&'static ())
183
+ // y = x;
184
+ // ```
185
+ //
186
+ // We wind up ultimately with constraints like
187
+ //
188
+ // ```rust
189
+ // !a: 'temp1 // from the `y = x` statement
190
+ // 'temp1: 'temp2
191
+ // 'temp2: 'static // from the AscribeUserType
192
+ // ```
193
+ //
194
+ // and here we prefer to blame the source (the y = x statement).
195
+ let blame_source = match from_region_origin {
161
196
NLLRegionVariableOrigin :: FreeRegion
162
197
| NLLRegionVariableOrigin :: Existential { from_forall : false } => {
163
198
true
@@ -173,7 +208,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
173
208
174
209
let constraint_sup_scc = self . constraint_sccs . scc ( constraint. sup ) ;
175
210
176
- if should_reverse {
211
+ if blame_source {
177
212
match categorized_path[ * i] . 0 {
178
213
ConstraintCategory :: OpaqueType | ConstraintCategory :: Boring |
179
214
ConstraintCategory :: BoringNoLocation | ConstraintCategory :: Internal => false ,
@@ -190,14 +225,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
190
225
}
191
226
} ;
192
227
193
- let best_choice = if should_reverse {
228
+ let best_choice = if blame_source {
194
229
range. rev ( ) . find ( find_region)
195
230
} else {
196
231
range. find ( find_region)
197
232
} ;
198
233
199
- debug ! ( "best_blame_constraint: best_choice={:?} should_reverse ={}" ,
200
- best_choice, should_reverse ) ;
234
+ debug ! ( "best_blame_constraint: best_choice={:?} blame_source ={}" ,
235
+ best_choice, blame_source ) ;
201
236
202
237
if let Some ( i) = best_choice {
203
238
if let Some ( next) = categorized_path. get ( i + 1 ) {
0 commit comments