Skip to content

Commit 76c1454

Browse files
authored
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
2 parents 7c404ce + 1a4f6b8 commit 76c1454

13 files changed

+89
-16
lines changed

src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
5454
err.span_suggestion(
5555
fn_return_span,
5656
&format!(
57-
"you can add a constraint to the return type to make it last \
57+
"you can add a bound to the return type to make it last \
5858
less than `'static` and match {}",
5959
lifetime,
6060
),

src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc::mir::{
99
use rustc::ty::adjustment::PointerCast;
1010
use rustc::ty::{self, TyCtxt};
1111
use rustc_data_structures::fx::FxHashSet;
12-
use rustc_errors::DiagnosticBuilder;
12+
use rustc_errors::{Applicability, DiagnosticBuilder};
1313
use rustc_index::vec::IndexVec;
1414
use rustc_span::symbol::Symbol;
1515
use rustc_span::Span;
@@ -206,6 +206,47 @@ impl BorrowExplanation {
206206
),
207207
);
208208
};
209+
210+
self.add_lifetime_bound_suggestion_to_diagnostic(
211+
tcx,
212+
err,
213+
&category,
214+
span,
215+
region_name,
216+
);
217+
}
218+
_ => {}
219+
}
220+
}
221+
pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic<'tcx>(
222+
&self,
223+
tcx: TyCtxt<'tcx>,
224+
err: &mut DiagnosticBuilder<'_>,
225+
category: &ConstraintCategory,
226+
span: Span,
227+
region_name: &RegionName,
228+
) {
229+
match category {
230+
ConstraintCategory::OpaqueType => {
231+
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
232+
let suggestable_name = if region_name.was_named() {
233+
region_name.to_string()
234+
} else {
235+
"'_".to_string()
236+
};
237+
238+
err.span_suggestion(
239+
span,
240+
&format!(
241+
"you can add a bound to the {}to make it last less than \
242+
`'static` and match `{}`",
243+
category.description(),
244+
region_name,
245+
),
246+
format!("{} + {}", snippet, suggestable_name),
247+
Applicability::Unspecified,
248+
);
249+
}
209250
}
210251
_ => {}
211252
}

src/librustc_mir/borrow_check/diagnostics/region_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
815815
span,
816816
&format!(
817817
"to allow this `impl Trait` to capture borrowed data with lifetime \
818-
`{}`, add `{}` as a constraint",
818+
`{}`, add `{}` as a bound",
819819
fr_name, suggestable_fr_name,
820820
),
821821
format!("{} + {}", snippet, suggestable_fr_name),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct List {
2+
data: Vec<String>,
3+
}
4+
impl List {
5+
fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
6+
self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
7+
//~^ ERROR does not live long enough
8+
}
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0597]: `prefix` does not live long enough
2+
--> $DIR/does-not-live-long-enough.rs:6:51
3+
|
4+
LL | fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
5+
| -- lifetime `'a` defined here --------------------------- opaque type requires that `prefix` is borrowed for `'a`
6+
LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
7+
| --- ^^^^^^ borrowed value does not live long enough
8+
| |
9+
| value captured here
10+
LL |
11+
LL | }
12+
| - `prefix` dropped here while still borrowed
13+
|
14+
help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
15+
|
16+
LL | fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> + 'a {
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0597`.

src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
55
| -- lifetime `'a` defined here ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
66
|
77
= help: consider replacing `'a` with `'static`
8-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
8+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
99
|
1010
LL | type E<'a, 'b> = impl Sized; + 'a
1111
|

src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
66
| |
77
| let's call the lifetime of this reference `'1`
88
|
9-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
9+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
1010
|
1111
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
1212
| ^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
2020
| lifetime `'a` defined here
2121
|
2222
= help: consider replacing `'a` with `'static`
23-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
23+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
2424
|
2525
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
2626
| ^^^^^^^^^^^^^^

src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ note: ...can't outlive the anonymous lifetime #1 defined on the function body at
1111
|
1212
LL | fn elided(x: &i32) -> impl Copy { x }
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14-
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
14+
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
1515
|
1616
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
1717
| ^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13
2929
|
3030
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
3131
| ^^
32-
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
32+
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
3333
|
3434
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
3535
| ^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ note: ...can't outlive the lifetime `'a` as defined on the function body at 12:1
4747
|
4848
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
4949
| ^^
50-
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
50+
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
5151
|
5252
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
5353
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
66
| |
77
| let's call the lifetime of this reference `'1`
88
|
9-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
9+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
1010
|
1111
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
1212
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
2020
| lifetime `'a` defined here
2121
|
2222
= help: consider replacing `'a` with `'static`
23-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
23+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
2424
|
2525
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/test/ui/impl-trait/static-return-lifetime-infered.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | / fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
1515
LL | | self.x.iter().map(|a| a.0)
1616
LL | | }
1717
| |_____^
18-
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
18+
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
1919
|
2020
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20
3535
|
3636
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
3737
| ^^
38-
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
38+
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
3939
|
4040
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
66
| |
77
| let's call the lifetime of this reference `'1`
88
|
9-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
9+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
1010
|
1111
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
1212
| ^^^^^^^^^^^^^^^

src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self }
66
| |
77
| let's call the lifetime of this reference `'1`
88
|
9-
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
9+
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
1010
|
1111
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
1212
| ^^^^^^^^^^^^^^^

src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ note: ...can't outlive the anonymous lifetime #1 defined on the method body at 8
1111
|
1212
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14-
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
14+
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
1515
|
1616
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
1717
| ^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)