about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-01-03 17:56:21 +0900
committerGitHub <noreply@github.com>2020-01-03 17:56:21 +0900
commit76c1454d27440dd6783bcc81b8558510a18130bf (patch)
tree7c7d8a2b52fed8b45e1d42200629a2f96ff141a9
parent7c404ce2332e72bc8e2bed8f14ab0e0e6002d2af (diff)
parent1a4f6b85a745e9855bbad4c5fdf0806200133f1d (diff)
downloadrust-76c1454d27440dd6783bcc81b8558510a18130bf.tar.gz
rust-76c1454d27440dd6783bcc81b8558510a18130bf.zip
Rollup merge of #67595 - ohadravid:impl-trait-does-not-live-long-enough, r=estebank
Suggest adding a lifetime constraint for opaque type

Fixes #67577, where code like this:

```
struct List {
  data: Vec<String>,
}
impl List {
  fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
    self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
  }
}
```

will show this error:
```
   Compiling playground v0.0.1 (/playground)
error[E0597]: `prefix` does not live long enough
 --> src/lib.rs:6:47
  |
5 |   fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
  |                   -- lifetime `'a` defined here     --------------------------- opaque type requires that `prefix` is borrowed for `'a`
...
```

but without suggesting the lovely `help: you can add a constraint..`.

r? @estebank
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs43
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs2
-rw-r--r--src/test/ui/impl-trait/does-not-live-long-enough.rs11
-rw-r--r--src/test/ui/impl-trait/does-not-live-long-enough.stderr21
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr2
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr4
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr6
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr4
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr4
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr2
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr2
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr2
13 files changed, 89 insertions, 16 deletions
diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 8f6fbd27a58..69ebbe1fd36 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -54,7 +54,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             err.span_suggestion(
                                 fn_return_span,
                                 &format!(
-                                    "you can add a constraint to the return type to make it last \
+                                    "you can add a bound to the return type to make it last \
                                  less than `'static` and match {}",
                                     lifetime,
                                 ),
diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index 58f62bf7e40..9a0c99b07e6 100644
--- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -9,7 +9,7 @@ use rustc::mir::{
 use rustc::ty::adjustment::PointerCast;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_index::vec::IndexVec;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -206,6 +206,47 @@ impl BorrowExplanation {
                         ),
                     );
                 };
+
+                self.add_lifetime_bound_suggestion_to_diagnostic(
+                    tcx,
+                    err,
+                    &category,
+                    span,
+                    region_name,
+                );
+            }
+            _ => {}
+        }
+    }
+    pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic<'tcx>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        category: &ConstraintCategory,
+        span: Span,
+        region_name: &RegionName,
+    ) {
+        match category {
+            ConstraintCategory::OpaqueType => {
+                if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
+                    let suggestable_name = if region_name.was_named() {
+                        region_name.to_string()
+                    } else {
+                        "'_".to_string()
+                    };
+
+                    err.span_suggestion(
+                        span,
+                        &format!(
+                            "you can add a bound to the {}to make it last less than \
+                             `'static` and match `{}`",
+                            category.description(),
+                            region_name,
+                        ),
+                        format!("{} + {}", snippet, suggestable_name),
+                        Applicability::Unspecified,
+                    );
+                }
             }
             _ => {}
         }
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index f45246301d3..09b487ba1da 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -815,7 +815,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                             span,
                             &format!(
                                 "to allow this `impl Trait` to capture borrowed data with lifetime \
-                                 `{}`, add `{}` as a constraint",
+                                 `{}`, add `{}` as a bound",
                                 fr_name, suggestable_fr_name,
                             ),
                             format!("{} + {}", snippet, suggestable_fr_name),
diff --git a/src/test/ui/impl-trait/does-not-live-long-enough.rs b/src/test/ui/impl-trait/does-not-live-long-enough.rs
new file mode 100644
index 00000000000..6179132b3f6
--- /dev/null
+++ b/src/test/ui/impl-trait/does-not-live-long-enough.rs
@@ -0,0 +1,11 @@
+struct List {
+    data: Vec<String>,
+}
+impl List {
+    fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
+        self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
+        //~^ ERROR does not live long enough
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/does-not-live-long-enough.stderr b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
new file mode 100644
index 00000000000..83d0f87015b
--- /dev/null
+++ b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
@@ -0,0 +1,21 @@
+error[E0597]: `prefix` does not live long enough
+  --> $DIR/does-not-live-long-enough.rs:6:51
+   |
+LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
+   |                     -- lifetime `'a` defined here     --------------------------- opaque type requires that `prefix` is borrowed for `'a`
+LL |         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
+   |                                 ---               ^^^^^^ borrowed value does not live long enough
+   |                                 |
+   |                                 value captured here
+LL |
+LL |     }
+   |     - `prefix` dropped here while still borrowed
+   |
+help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
+   |
+LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> + 'a {
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
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 45c5142d93f..4c38f0a8a91 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -5,7 +5,7 @@ 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
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
 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 bb5a85aba97..1806d2607a3 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
@@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
    |              |
    |              let's call the lifetime of this reference `'1`
    |
-help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                       ^^^^^^^^^^^^^^
@@ -20,7 +20,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
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                ^^^^^^^^^^^^^^
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index a8341f62e1d..7f92e709af5 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -11,7 +11,7 @@ note: ...can't outlive the anonymous lifetime #1 defined on the function body at
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1
+help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                       ^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             ^^
-help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13
+help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                ^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ note: ...can't outlive the lifetime `'a` as defined on the function body at 12:1
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               ^^
-help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15
+help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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 22f081b79f1..123ea6af6b0 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
@@ -6,7 +6,7 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
    |                         |
    |                         let's call the lifetime of this reference `'1`
    |
-help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,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
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index 1d6b5f56aa0..e550be19174 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -15,7 +15,7 @@ LL | /     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
 LL | |         self.x.iter().map(|a| a.0)
 LL | |     }
    | |_____^
-help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5
+help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    ^^
-help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20
+help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
index 5a63553adc5..f2e556c63cb 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr
@@ -6,7 +6,7 @@ LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
    |                          |
    |                          let's call the lifetime of this reference `'1`
    |
-help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                                     ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
index b46c6b9b713..b76966e8693 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
    |                    |
    |                    let's call the lifetime of this reference `'1`
    |
-help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                               ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 5118280e7ec..9f541499515 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -11,7 +11,7 @@ note: ...can't outlive the anonymous lifetime #1 defined on the method body at 8
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 8:5
+help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 8:5
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                               ^^^^^^^^^^^^^^^