未验证 提交 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> { ...@@ -54,7 +54,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
err.span_suggestion( err.span_suggestion(
fn_return_span, fn_return_span,
&format!( &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 {}", less than `'static` and match {}",
lifetime, lifetime,
), ),
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
use rustc::ty::adjustment::PointerCast; use rustc::ty::adjustment::PointerCast;
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagnosticBuilder; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::Span; use rustc_span::Span;
...@@ -206,6 +206,47 @@ pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'tcx>( ...@@ -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( ...@@ -815,7 +815,7 @@ fn add_static_impl_trait_suggestion(
span, span,
&format!( &format!(
"to allow this `impl Trait` to capture borrowed data with lifetime \ "to allow this `impl Trait` to capture borrowed data with lifetime \
`{}`, add `{}` as a constraint", `{}`, add `{}` as a bound",
fr_name, suggestable_fr_name, fr_name, suggestable_fr_name,
), ),
format!("{} + {}", snippet, 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> { ...@@ -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` | -- lifetime `'a` defined here ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
| |
= help: consider replacing `'a` with `'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 LL | type E<'a, 'b> = impl Sized; + 'a
| |
......
...@@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x } ...@@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
| | | |
| let's call the lifetime of this reference `'1` | 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 } LL | fn elided(x: &i32) -> impl Copy + '_ { x }
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
...@@ -20,7 +20,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } ...@@ -20,7 +20,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| lifetime `'a` defined here | lifetime `'a` defined here
| |
= help: consider replacing `'a` with `'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 | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } 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 ...@@ -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 } 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 } 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 ...@@ -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 } 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 } 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 ...@@ -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 } 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 } 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> { ...@@ -6,7 +6,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| | | |
| let's call the lifetime of this reference `'1` | 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> + '_ { 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> { ...@@ -20,7 +20,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| lifetime `'a` defined here | lifetime `'a` defined here
| |
= help: consider replacing `'a` with `'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 | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a { 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> { ...@@ -15,7 +15,7 @@ LL | / fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
LL | | self.x.iter().map(|a| a.0) LL | | self.x.iter().map(|a| a.0)
LL | | } 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> + '_ { 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 ...@@ -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> { 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 { 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 } ...@@ -6,7 +6,7 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| | | |
| let's call the lifetime of this reference `'1` | 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 } LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
......
...@@ -6,7 +6,7 @@ LL | 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` | 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 } 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 ...@@ -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 } 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 } 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.
先完成此消息的编辑!
想要评论请 注册