diff options
| author | bors <bors@rust-lang.org> | 2019-11-18 22:08:31 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-11-18 22:08:31 +0000 |
| commit | 0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8 (patch) | |
| tree | def8d2158300c8de61bada8c86b8fc835f02ed5e /src/test/ui/lifetimes | |
| parent | 3e525e3f6d9e85d54fa4c49b52df85aa0c990100 (diff) | |
| parent | cba0761e5f3677b90390fe7aee1eeda684296658 (diff) | |
| download | rust-0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8.tar.gz rust-0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8.zip | |
Auto merge of #58281 - mark-i-m:synthesis, r=estebank
Add outlives suggestions for some lifetime errors
This PR implements suggestion diagnostics for some lifetime mismatch errors. When the borrow checker finds that some lifetime 'a doesn't outlive some other lifetime 'b that it should outlive, then in addition to the current lifetime error, we also emit a suggestion for how to fix the problem by adding a bound:
- If a and b are normal named regions, suggest to add the bound `'a: 'b`
- If b is static, suggest to replace a with static
- If b also needs to outlive a, they must be the same, so suggest unifying them
We start with a simpler implementation that avoids diagnostic regression or implementation complexity:
- We only makes suggestions for lifetimes the user can already name (eg not closure regions or elided regions)
- For now, we only emit a help note, not an actually suggestion because it is significantly easier.
Finally, there is one hack: it seems that implicit regions in async fn are given the name '_ incorrectly. To avoid suggesting '_: 'x, we simply filter out such lifetimes by name.
For more info, see this internals thread:
https://internals.rust-lang.org/t/mechanical-suggestions-for-some-borrow-checker-errors/9049/3
TL;DR Make suggestions to add a `where 'a: 'b` constraint for some lifetime errors. Details are in the paper linked from the internals thread above.
r? @estebank
TODO
- [x] Clean up code
- [x] Only make idiomatic suggestions
- [x] don't suggest naming `&'a self`
- [x] rather than `'a: 'static`, suggest replacing `'a` with `'static`
- [x] rather than `'a: 'b, 'b: 'a`, suggest replacing `'a` with `'b` or vice versa
- [x] Performance (maybe need a perf run when this is closer to the finish line?)
- perf run was clean...
- EDIT: perf run seems to only check non-error performance... How do we check that error performance didn't regress?
- [x] Needs ui tests
- [x] Integrate the `help` message into the main lifetime `error`
Diffstat (limited to 'src/test/ui/lifetimes')
7 files changed, 16 insertions, 0 deletions
diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr index f2cf19abdac..60420973e1e 100644 --- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr @@ -6,6 +6,8 @@ LL | fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) { LL | // but ref_obj will not, so warn. LL | ref_obj(x) | ^^^^^^^^^^ `x` escapes the function body here + | + = help: consider replacing `'a` with `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:39:5 @@ -15,6 +17,8 @@ LL | fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) { LL | // same as test2, but cross crate LL | lib::ref_obj(x) | ^^^^^^^^^^^^^^^ `x` escapes the function body here + | + = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr index fbefa1f5667..99fab4631a2 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr @@ -8,6 +8,8 @@ LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) { LL | let z = Ref { data: y.data }; LL | x.push(z); | ^^^^^^^^^ argument requires that `'c` must outlive `'b` + | + = help: consider adding the following bound: `'c: 'b` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr index d889eb4afdb..52c5752f6ea 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr @@ -8,6 +8,8 @@ LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) { ... LL | a.push(b); | ^^^^^^^^^ argument requires that `'c` must outlive `'b` + | + = help: consider adding the following bound: `'c: 'b` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr index 39eb4079352..e90c81ee3e1 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr @@ -8,6 +8,8 @@ LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) { ... LL | Vec::push(a, b); | ^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b` + | + = help: consider adding the following bound: `'c: 'b` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr index a39bb165806..b3d0bc2b882 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr @@ -8,6 +8,8 @@ LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) ... LL | x.push(y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr index 48ce5301ade..fbe98a4263e 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr @@ -7,6 +7,8 @@ LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) { | lifetime `'a` defined here LL | x.push(y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr index 09960683980..1e24032fc1c 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr @@ -7,6 +7,8 @@ LL | fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) { | lifetime `'a` defined here LL | x.push(y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` error: aborting due to previous error |
