未验证 提交 76c1454d 编写于 作者: Y Yuki Okushi 提交者: GitHub

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
......@@ -54,7 +54,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
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,
),
......
......@@ -9,7 +9,7 @@
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 @@ pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'tcx>(
),
);
};
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,
);
}
}
_ => {}
}
......
......@@ -815,7 +815,7 @@ fn add_static_impl_trait_suggestion(
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),
......
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() {}
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`.
......@@ -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
|
......
......@@ -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 }
| ^^^^^^^^^^^^^^
......
......@@ -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 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -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 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -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 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......
......@@ -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 }
| ^^^^^^^^^^^^^^^
......
......@@ -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 }
| ^^^^^^^^^^^^^^^
......
......@@ -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 }
| ^^^^^^^^^^^^^^^
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册