Skip to content

Commit ba54ef8

Browse files
committed
Add comments, rename variable
1 parent 9c5a5c4 commit ba54ef8

File tree

1 file changed

+40
-5
lines changed
  • src/librustc_mir/borrow_check/nll/region_infer/error_reporting

1 file changed

+40
-5
lines changed

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,42 @@ impl<'tcx> RegionInferenceContext<'tcx> {
157157
let target_scc = self.constraint_sccs.scc(target_region);
158158
let mut range = 0..path.len();
159159

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 {
161196
NLLRegionVariableOrigin::FreeRegion
162197
| NLLRegionVariableOrigin::Existential { from_forall: false } => {
163198
true
@@ -173,7 +208,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
173208

174209
let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
175210

176-
if should_reverse {
211+
if blame_source {
177212
match categorized_path[*i].0 {
178213
ConstraintCategory::OpaqueType | ConstraintCategory::Boring |
179214
ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false,
@@ -190,14 +225,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
190225
}
191226
};
192227

193-
let best_choice = if should_reverse {
228+
let best_choice = if blame_source {
194229
range.rev().find(find_region)
195230
} else {
196231
range.find(find_region)
197232
};
198233

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);
201236

202237
if let Some(i) = best_choice {
203238
if let Some(next) = categorized_path.get(i + 1) {

0 commit comments

Comments
 (0)