improve heuristics for what makes an interesting constraint

This commit is contained in:
Niko Matsakis 2018-07-25 16:36:03 +03:00
parent 76991ea237
commit 0d918a8575
10 changed files with 87 additions and 41 deletions

View File

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

View File

@ -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<Item=u32> {
| - 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<Item=u32> {
| -------- `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

View File

@ -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

View File

@ -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

View File

@ -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
},
);
}

View File

@ -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 | | },
| |_________^
|

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
| - 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`
| ________________-___________________________________^
| | |
| | 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