about summary refs log tree commit diff
path: root/src/test/ui/impl-trait
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-18 22:08:31 +0000
committerbors <bors@rust-lang.org>2019-11-18 22:08:31 +0000
commit0ccee30773050f6bf50fd6ceb9ac61e6d58aa4d8 (patch)
treedef8d2158300c8de61bada8c86b8fc835f02ed5e /src/test/ui/impl-trait
parent3e525e3f6d9e85d54fa4c49b52df85aa0c990100 (diff)
parentcba0761e5f3677b90390fe7aee1eeda684296658 (diff)
downloadrust-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/impl-trait')
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr1
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr4
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr1
3 files changed, 6 insertions, 0 deletions
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
index 82e280b9fb2..45c5142d93f 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -4,6 +4,7 @@ error: lifetime may not live long enough
 LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
    |        -- lifetime `'a` defined here                   ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
    |
+   = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL | type E<'a, 'b> = impl Sized; + 'a
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 097f003575e..bb5a85aba97 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -19,6 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             |
    |             lifetime `'a` defined here
    |
+   = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
@@ -31,6 +32,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
    |
    = help: consider replacing `'a` with `'static`
+   = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:17:61
@@ -39,6 +41,8 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                          --  -- lifetime `'b` defined here  ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
    |                          |
    |                          lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'b: 'a`
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:22:51
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 423cfcc4989..22f081b79f1 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
@@ -19,6 +19,7 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    |
    |                    lifetime `'a` defined here
    |
+   = help: consider replacing `'a` with `'static`
 help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {