diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index d329718cf94..1b540ef74be 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -104,7 +104,48 @@ impl<'tcx> RegionInferenceContext<'tcx> { categorized_path ); - // Find what appears to be the most interesting path to report to the user. + // To find the best span to cite, we first try to look for the + // final constraint that is interesting and where the `sup` is + // not unified with the ultimate target region. The reason + // for this is that we have a chain of constraints that lead + // from the source to the target region, something like: + // + // '0: '1 ('0 is the source) + // '1: '2 + // '2: '3 + // '3: '4 + // '4: '5 + // '5: '6 ('6 is the target) + // + // Some of those regions are unified with `'6` (in the same + // SCC). We want to screen those out. After that point, the + // "closest" constraint we have to the end is going to be the + // most likely to be the point where the value escapes -- but + // we still want to screen for an "interesting" point to + // highlight (e.g., a call site or something). + let target_scc = self.constraint_sccs.scc(target_region); + let best_choice = (0..path.len()).rev().find(|&i| { + let constraint = &self.constraints[path[i]]; + + let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); + if constraint_sup_scc == target_scc { + return false; + } + + match categorized_path[i].0 { + ConstraintCategory::Boring => false, + _ => true, + } + }); + if let Some(i) = best_choice { + let (category, span) = categorized_path[i]; + return (category, span, target_region); + } + + // If that search fails, that is.. unusual. Maybe everything + // is in the same SCC or something. In that case, find what + // appears to be the most interesting point to report to the + // user via an even more ad-hoc guess. categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0)); debug!("best_blame_constraint: sorted_path={:#?}", categorized_path); diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 4c0b3a5d931..c6f8d2e519c 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -10,19 +10,21 @@ warning: not reporting region error due to nll LL | self.x.iter().map(|a| a.0) | ^^^^ -error: unsatisfied lifetime constraints +error: borrowed data escapes outside of closure --> $DIR/static-return-lifetime-infered.rs:17:9 | LL | fn iter_values_anon(&self) -> impl Iterator { - | - let's call the lifetime of this reference `'1` + | ----- `self` is a reference that is only valid in the closure body LL | self.x.iter().map(|a| a.0) - | ^^^^^^ cast requires that `'1` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here -error: unsatisfied lifetime constraints +error: borrowed data escapes outside of closure --> $DIR/static-return-lifetime-infered.rs:21:9 | +LL | fn iter_values<'a>(&'a self) -> impl Iterator { + | -------- `self` is a reference that is only valid in the closure body LL | self.x.iter().map(|a| a.0) - | ^^^^^^ cast requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-40288-2.nll.stderr b/src/test/ui/issue-40288-2.nll.stderr index 319e7ef3860..1d2b2660342 100644 --- a/src/test/ui/issue-40288-2.nll.stderr +++ b/src/test/ui/issue-40288-2.nll.stderr @@ -35,22 +35,22 @@ LL | let mut out = Struct { head: x, _tail: [()] }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0621]: explicit lifetime required in the type of `y` - --> $DIR/issue-40288-2.rs:16:31 + --> $DIR/issue-40288-2.rs:17:9 | LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { | - consider changing the type of `y` to `&'a T` ... -LL | let slice: &mut [_] = &mut out; - | ^^^^^^^^ lifetime `'a` required +LL | slice[0] = y; + | ^^^^^^^^^^^^ lifetime `'a` required error[E0621]: explicit lifetime required in the type of `y` - --> $DIR/issue-40288-2.rs:31:41 + --> $DIR/issue-40288-2.rs:32:9 | LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { | - consider changing the type of `y` to `&'a T` ... -LL | let dst: &mut Struct<_, [()]> = &mut out; - | ^^^^^^^^ lifetime `'a` required +LL | dst.head = y; + | ^^^^^^^^^^^^ lifetime `'a` required error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr index 61af34747ca..c43c4ce3a0c 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr @@ -11,20 +11,20 @@ LL | z.push((x,y)); //~ ERROR lifetime mismatch | ^ error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-3.rs:11:33 + --> $DIR/ex3-both-anon-regions-3.rs:12:5 | LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | --- ^ --- these two types are declared with different lifetimes... - | | - | ...but data flows into `z` here + | --- --- these two types are declared with different lifetimes... +LL | z.push((x,y)); //~ ERROR lifetime mismatch + | ^^^^^^^^^^^^^ ...but data flows into `z` here error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-3.rs:11:36 + --> $DIR/ex3-both-anon-regions-3.rs:12:5 | LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | --- ^ --- these two types are declared with different lifetimes... - | | - | ...but data flows into `z` here + | --- --- these two types are declared with different lifetimes... +LL | z.push((x,y)); //~ ERROR lifetime mismatch + | ^^^^^^^^^^^^^ ...but data flows into `z` here error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs index 39050864768..b879f9a3398 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs @@ -52,9 +52,9 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell cell_c, |_outlives1, _outlives2, _outlives3, x, y| { // Only works if 'x: 'y: - let p = x.get(); //~ ERROR + let p = x.get(); //~^ WARN not reporting region error due to nll - demand_y(x, y, p) + demand_y(x, y, p) //~ ERROR }, ); } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 6588cbe8bdf..a7a50a3a029 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -1,28 +1,28 @@ warning: not reporting region error due to nll --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21 | -LL | let p = x.get(); //~ ERROR +LL | let p = x.get(); | ^^^^^^^ error: unsatisfied lifetime constraints - --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21 + --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13 | LL | |_outlives1, _outlives2, _outlives3, x, y| { | ---------- ---------- lifetime `'2` appears in this argument | | | lifetime `'1` appears in this argument -LL | // Only works if 'x: 'y: -LL | let p = x.get(); //~ ERROR - | ^^^^^^^ argument requires that `'1` must outlive `'2` +... +LL | demand_y(x, y, p) //~ ERROR + | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9 | LL | / |_outlives1, _outlives2, _outlives3, x, y| { LL | | // Only works if 'x: 'y: -LL | | let p = x.get(); //~ ERROR +LL | | let p = x.get(); LL | | //~^ WARN not reporting region error due to nll -LL | | demand_y(x, y, p) +LL | | demand_y(x, y, p) //~ ERROR LL | | }, | |_________^ | diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index d51ba8201aa..b8e8fae14b0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -5,7 +5,7 @@ LL | foo(cell, |cell_a, cell_x| { | ^^^ error: borrowed data escapes outside of closure - --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:20 + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9 | LL | foo(cell, |cell_a, cell_x| { | ------ ------ `cell_x` is a reference that is only valid in the closure body @@ -13,7 +13,7 @@ LL | foo(cell, |cell_a, cell_x| { | `cell_a` is declared here, outside of the closure body LL | //~^ WARNING not reporting region error due to nll LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure - | ^^^^^^^^^^^^ `cell_x` escapes the closure body here + | ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15 diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index c75b3e6670c..fb98c506c7d 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -5,7 +5,7 @@ LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ error: unsatisfied lifetime constraints - --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:24 + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | --------- - lifetime `'1` appears in this argument @@ -13,7 +13,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | lifetime `'2` appears in this argument LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) - | ^^^^^^^ argument requires that `'1` must outlive `'2` + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47 diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 2465219ee55..73d39a8502b 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -5,7 +5,7 @@ LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ error: unsatisfied lifetime constraints - --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:24 + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { | ---------- ---------- lifetime `'2` appears in this argument @@ -13,7 +13,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | lifetime `'1` appears in this argument LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) - | ^^^^^^^ argument requires that `'1` must outlive `'2` + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47 diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 6385578698c..5b4c669c66e 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -23,13 +23,16 @@ LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^^^^^^^^^^^^^^^^^^ error: unsatisfied lifetime constraints - --> $DIR/dyn-trait-underscore.rs:18:5 + --> $DIR/dyn-trait-underscore.rs:16:52 | -LL | fn a(items: &[T]) -> Box> { - | - let's call the lifetime of this reference `'1` -LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` -LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime - | ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` +LL | fn a(items: &[T]) -> Box> { + | ________________-___________________________________^ + | | | + | | let's call the lifetime of this reference `'1` +LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime +LL | | } + | |_^ return requires that `'1` must outlive `'static` error: aborting due to previous error