Skip to content

Commit 0d918a8

Browse files
committed
improve heuristics for what makes an interesting constraint
1 parent 76991ea commit 0d918a8

10 files changed

+87
-41
lines changed

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

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,48 @@ impl<'tcx> RegionInferenceContext<'tcx> {
104104
categorized_path
105105
);
106106

107-
// Find what appears to be the most interesting path to report to the user.
107+
// To find the best span to cite, we first try to look for the
108+
// final constraint that is interesting and where the `sup` is
109+
// not unified with the ultimate target region. The reason
110+
// for this is that we have a chain of constraints that lead
111+
// from the source to the target region, something like:
112+
//
113+
// '0: '1 ('0 is the source)
114+
// '1: '2
115+
// '2: '3
116+
// '3: '4
117+
// '4: '5
118+
// '5: '6 ('6 is the target)
119+
//
120+
// Some of those regions are unified with `'6` (in the same
121+
// SCC). We want to screen those out. After that point, the
122+
// "closest" constraint we have to the end is going to be the
123+
// most likely to be the point where the value escapes -- but
124+
// we still want to screen for an "interesting" point to
125+
// highlight (e.g., a call site or something).
126+
let target_scc = self.constraint_sccs.scc(target_region);
127+
let best_choice = (0..path.len()).rev().find(|&i| {
128+
let constraint = &self.constraints[path[i]];
129+
130+
let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
131+
if constraint_sup_scc == target_scc {
132+
return false;
133+
}
134+
135+
match categorized_path[i].0 {
136+
ConstraintCategory::Boring => false,
137+
_ => true,
138+
}
139+
});
140+
if let Some(i) = best_choice {
141+
let (category, span) = categorized_path[i];
142+
return (category, span, target_region);
143+
}
144+
145+
// If that search fails, that is.. unusual. Maybe everything
146+
// is in the same SCC or something. In that case, find what
147+
// appears to be the most interesting point to report to the
148+
// user via an even more ad-hoc guess.
108149
categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
109150
debug!("best_blame_constraint: sorted_path={:#?}", categorized_path);
110151

src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,21 @@ warning: not reporting region error due to nll
1010
LL | self.x.iter().map(|a| a.0)
1111
| ^^^^
1212

13-
error: unsatisfied lifetime constraints
13+
error: borrowed data escapes outside of closure
1414
--> $DIR/static-return-lifetime-infered.rs:17:9
1515
|
1616
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
17-
| - let's call the lifetime of this reference `'1`
17+
| ----- `self` is a reference that is only valid in the closure body
1818
LL | self.x.iter().map(|a| a.0)
19-
| ^^^^^^ cast requires that `'1` must outlive `'static`
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here
2020

21-
error: unsatisfied lifetime constraints
21+
error: borrowed data escapes outside of closure
2222
--> $DIR/static-return-lifetime-infered.rs:21:9
2323
|
24+
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
25+
| -------- `self` is a reference that is only valid in the closure body
2426
LL | self.x.iter().map(|a| a.0)
25-
| ^^^^^^ cast requires that `'a` must outlive `'static`
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here
2628

2729
error: aborting due to 2 previous errors
2830

src/test/ui/issue-40288-2.nll.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,22 @@ LL | let mut out = Struct { head: x, _tail: [()] };
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3636

3737
error[E0621]: explicit lifetime required in the type of `y`
38-
--> $DIR/issue-40288-2.rs:16:31
38+
--> $DIR/issue-40288-2.rs:17:9
3939
|
4040
LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
4141
| - consider changing the type of `y` to `&'a T`
4242
...
43-
LL | let slice: &mut [_] = &mut out;
44-
| ^^^^^^^^ lifetime `'a` required
43+
LL | slice[0] = y;
44+
| ^^^^^^^^^^^^ lifetime `'a` required
4545

4646
error[E0621]: explicit lifetime required in the type of `y`
47-
--> $DIR/issue-40288-2.rs:31:41
47+
--> $DIR/issue-40288-2.rs:32:9
4848
|
4949
LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
5050
| - consider changing the type of `y` to `&'a T`
5151
...
52-
LL | let dst: &mut Struct<_, [()]> = &mut out;
53-
| ^^^^^^^^ lifetime `'a` required
52+
LL | dst.head = y;
53+
| ^^^^^^^^^^^^ lifetime `'a` required
5454

5555
error: aborting due to 2 previous errors
5656

src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ LL | z.push((x,y)); //~ ERROR lifetime mismatch
1111
| ^
1212

1313
error[E0623]: lifetime mismatch
14-
--> $DIR/ex3-both-anon-regions-3.rs:11:33
14+
--> $DIR/ex3-both-anon-regions-3.rs:12:5
1515
|
1616
LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
17-
| --- ^ --- these two types are declared with different lifetimes...
18-
| |
19-
| ...but data flows into `z` here
17+
| --- --- these two types are declared with different lifetimes...
18+
LL | z.push((x,y)); //~ ERROR lifetime mismatch
19+
| ^^^^^^^^^^^^^ ...but data flows into `z` here
2020

2121
error[E0623]: lifetime mismatch
22-
--> $DIR/ex3-both-anon-regions-3.rs:11:36
22+
--> $DIR/ex3-both-anon-regions-3.rs:12:5
2323
|
2424
LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
25-
| --- ^ --- these two types are declared with different lifetimes...
26-
| |
27-
| ...but data flows into `z` here
25+
| --- --- these two types are declared with different lifetimes...
26+
LL | z.push((x,y)); //~ ERROR lifetime mismatch
27+
| ^^^^^^^^^^^^^ ...but data flows into `z` here
2828

2929
error: aborting due to 2 previous errors
3030

src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell
5252
cell_c,
5353
|_outlives1, _outlives2, _outlives3, x, y| {
5454
// Only works if 'x: 'y:
55-
let p = x.get(); //~ ERROR
55+
let p = x.get();
5656
//~^ WARN not reporting region error due to nll
57-
demand_y(x, y, p)
57+
demand_y(x, y, p) //~ ERROR
5858
},
5959
);
6060
}

src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
warning: not reporting region error due to nll
22
--> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
33
|
4-
LL | let p = x.get(); //~ ERROR
4+
LL | let p = x.get();
55
| ^^^^^^^
66

77
error: unsatisfied lifetime constraints
8-
--> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
8+
--> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
99
|
1010
LL | |_outlives1, _outlives2, _outlives3, x, y| {
1111
| ---------- ---------- lifetime `'2` appears in this argument
1212
| |
1313
| lifetime `'1` appears in this argument
14-
LL | // Only works if 'x: 'y:
15-
LL | let p = x.get(); //~ ERROR
16-
| ^^^^^^^ argument requires that `'1` must outlive `'2`
14+
...
15+
LL | demand_y(x, y, p) //~ ERROR
16+
| ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
1717

1818
note: No external requirements
1919
--> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
2020
|
2121
LL | / |_outlives1, _outlives2, _outlives3, x, y| {
2222
LL | | // Only works if 'x: 'y:
23-
LL | | let p = x.get(); //~ ERROR
23+
LL | | let p = x.get();
2424
LL | | //~^ WARN not reporting region error due to nll
25-
LL | | demand_y(x, y, p)
25+
LL | | demand_y(x, y, p) //~ ERROR
2626
LL | | },
2727
| |_________^
2828
|

src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ LL | foo(cell, |cell_a, cell_x| {
55
| ^^^
66

77
error: borrowed data escapes outside of closure
8-
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:20
8+
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
99
|
1010
LL | foo(cell, |cell_a, cell_x| {
1111
| ------ ------ `cell_x` is a reference that is only valid in the closure body
1212
| |
1313
| `cell_a` is declared here, outside of the closure body
1414
LL | //~^ WARNING not reporting region error due to nll
1515
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
16-
| ^^^^^^^^^^^^ `cell_x` escapes the closure body here
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
1717

1818
note: No external requirements
1919
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15

src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ LL | demand_y(x, y, x.get())
55
| ^^^^^^^^^^^^^^^^^^^^^^^
66

77
error: unsatisfied lifetime constraints
8-
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:24
8+
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
99
|
1010
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
1111
| --------- - lifetime `'1` appears in this argument
1212
| |
1313
| lifetime `'2` appears in this argument
1414
LL | // Only works if 'x: 'y:
1515
LL | demand_y(x, y, x.get())
16-
| ^^^^^^^ argument requires that `'1` must outlive `'2`
16+
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
1717

1818
note: No external requirements
1919
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47

src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ LL | demand_y(x, y, x.get())
55
| ^^^^^^^^^^^^^^^^^^^^^^^
66

77
error: unsatisfied lifetime constraints
8-
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:24
8+
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
99
|
1010
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
1111
| ---------- ---------- lifetime `'2` appears in this argument
1212
| |
1313
| lifetime `'1` appears in this argument
1414
LL | // Only works if 'x: 'y:
1515
LL | demand_y(x, y, x.get())
16-
| ^^^^^^^ argument requires that `'1` must outlive `'2`
16+
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
1717

1818
note: No external requirements
1919
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47

src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
2323
| ^^^^^^^^^^^^^^^^^^^^^^
2424

2525
error: unsatisfied lifetime constraints
26-
--> $DIR/dyn-trait-underscore.rs:18:5
26+
--> $DIR/dyn-trait-underscore.rs:16:52
2727
|
28-
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
29-
| - let's call the lifetime of this reference `'1`
30-
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
31-
LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
32-
| ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
28+
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
29+
| ________________-___________________________________^
30+
| | |
31+
| | let's call the lifetime of this reference `'1`
32+
LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
33+
LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
34+
LL | | }
35+
| |_^ return requires that `'1` must outlive `'static`
3336

3437
error: aborting due to previous error
3538

0 commit comments

Comments
 (0)