Skip to content

Commit 130b9e9

Browse files
committed
Improve diagnostics when a static lifetime is expected
1 parent 3e018ce commit 130b9e9

26 files changed

+269
-176
lines changed

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs

+24-41
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
44
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
55
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
6-
use rustc_hir::intravisit::Visitor;
7-
use rustc_hir::FnRetTy;
86
use rustc_middle::ty;
97

108
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
@@ -48,19 +46,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4846
return None; // inapplicable
4947
};
5048

49+
// Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect,
50+
// and can steer users down the wrong path.
51+
if *named == ty::ReStatic {
52+
return None;
53+
}
54+
5155
debug!("try_report_named_anon_conflict: named = {:?}", named);
5256
debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
5357
debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
5458

55-
let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = (
56-
anon_param_info.param,
57-
anon_param_info.param_ty,
58-
anon_param_info.param_ty_span,
59-
anon_param_info.bound_region,
60-
anon_param_info.is_first,
61-
region_info.def_id,
62-
region_info.is_impl_item,
63-
);
59+
let param = anon_param_info.param;
60+
let new_ty = anon_param_info.param_ty;
61+
let new_ty_span = anon_param_info.param_ty_span;
62+
let br = anon_param_info.bound_region;
63+
let is_first = anon_param_info.is_first;
64+
let scope_def_id = region_info.def_id;
65+
let is_impl_item = region_info.is_impl_item;
66+
6467
match br {
6568
ty::BrAnon(_) => {}
6669
_ => {
@@ -75,26 +78,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
7578
return None;
7679
}
7780

78-
if let Some((_, fndecl)) = find_anon_type(self.tcx(), anon, &br) {
79-
if self.is_self_anon(is_first, scope_def_id) {
80-
return None;
81-
}
82-
83-
if let FnRetTy::Return(ty) = &fndecl.output {
84-
let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir());
85-
v.visit_ty(ty);
86-
87-
debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
88-
if sub == &ty::ReStatic
89-
&& v.0.into_iter().any(|t| t.span.desugaring_kind().is_none())
90-
{
91-
// If the failure is due to a `'static` requirement coming from a `dyn` or
92-
// `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case
93-
// better in `static_impl_trait`.
94-
debug!("try_report_named_anon_conflict: impl Trait + 'static");
95-
return None;
96-
}
97-
}
81+
if find_anon_type(self.tcx(), anon, &br).is_some()
82+
&& self.is_self_anon(is_first, scope_def_id)
83+
{
84+
return None;
9885
}
9986

10087
let (error_var, span_label_var) = match param.pat.simple_ident() {
@@ -114,16 +101,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
114101
);
115102

116103
diag.span_label(span, format!("lifetime `{}` required", named));
117-
// Suggesting `'static` is nearly always incorrect, and can steer users
118-
// down the wrong path.
119-
if *named != ty::ReStatic {
120-
diag.span_suggestion(
121-
new_ty_span,
122-
&format!("add explicit lifetime `{}` to {}", named, span_label_var),
123-
new_ty.to_string(),
124-
Applicability::Unspecified,
125-
);
126-
}
104+
diag.span_suggestion(
105+
new_ty_span,
106+
&format!("add explicit lifetime `{}` to {}", named, span_label_var),
107+
new_ty.to_string(),
108+
Applicability::Unspecified,
109+
);
127110

128111
Some(diag)
129112
}

src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
error[E0621]: explicit lifetime required in the type of `x`
1+
error[E0521]: borrowed data escapes outside of function
22
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
33
|
4+
LL | fn foo(x: &()) {
5+
| - - let's call the lifetime of this reference `'1`
6+
| |
7+
| `x` is a reference that is only valid in the function body
48
LL | / bar(|| {
59
LL | |
610
LL | | let _ = x;
711
LL | | })
8-
| |______^ lifetime `'static` required
12+
| | ^
13+
| | |
14+
| |______`x` escapes the function body here
15+
| argument requires that `'1` must outlive `'static`
916

1017
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
1118
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:9
@@ -31,5 +38,5 @@ LL | bar(move || {
3138

3239
error: aborting due to 2 previous errors
3340

34-
Some errors have detailed explanations: E0373, E0621.
41+
Some errors have detailed explanations: E0373, E0521.
3542
For more information about an error, try `rustc --explain E0373`.

src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ fn bar<F>(blk: F) where F: FnOnce() + 'static {
33

44
fn foo(x: &()) {
55
bar(|| {
6-
//~^ ERROR explicit lifetime required in the type of `x` [E0621]
6+
//~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
77
let _ = x;
88
})
99
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
error[E0621]: explicit lifetime required in the type of `x`
1+
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
2+
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:9
3+
|
4+
LL | fn foo(x: &()) {
5+
| --- this data with an anonymous lifetime `'_`...
6+
LL | bar(|| {
7+
| _________^
8+
LL | |
9+
LL | | let _ = x;
10+
LL | | })
11+
| |_____^ ...is captured here...
12+
|
13+
note: ...and is required to live as long as `'static` here
214
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
315
|
416
LL | bar(|| {
5-
| ^^^ lifetime `'static` required
17+
| ^^^
618

719
error: aborting due to previous error
820

9-
For more information about this error, try `rustc --explain E0621`.
21+
For more information about this error, try `rustc --explain E0759`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/generator-region-requirements.rs:13:51
3+
|
4+
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
5+
| - let's call the lifetime of this reference `'1`
6+
...
7+
LL | GeneratorState::Complete(c) => return c,
8+
| ^ returning this value requires that `'1` must outlive `'static`
9+
10+
error: aborting due to previous error
11+

src/test/ui/generator/generator-region-requirements.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ fn dangle(x: &mut i32) -> &'static mut i32 {
66
let mut g = || {
77
yield;
88
x
9+
//~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
910
};
1011
loop {
1112
match Pin::new(&mut g).resume(()) {
1213
GeneratorState::Complete(c) => return c,
13-
//~^ ERROR explicit lifetime required
1414
GeneratorState::Yielded(_) => (),
1515
}
1616
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
error[E0621]: explicit lifetime required in the type of `x`
2-
--> $DIR/generator-region-requirements.rs:12:51
1+
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
2+
--> $DIR/generator-region-requirements.rs:8:9
33
|
4+
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
5+
| -------- this data with an anonymous lifetime `'_`...
6+
...
7+
LL | x
8+
| ^ ...is captured here...
9+
...
410
LL | GeneratorState::Complete(c) => return c,
5-
| ^ lifetime `'static` required
11+
| - ...and is required to live as long as `'static` here
612

713
error: aborting due to previous error
814

9-
For more information about this error, try `rustc --explain E0621`.
15+
For more information about this error, try `rustc --explain E0759`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/projection-type-lifetime-mismatch.rs:17:5
3+
|
4+
LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | x.m()
7+
| ^^^^^ returning this value requires that `'1` must outlive `'static`
8+
9+
error: lifetime may not live long enough
10+
--> $DIR/projection-type-lifetime-mismatch.rs:22:5
11+
|
12+
LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
13+
| - let's call the lifetime of this reference `'1`
14+
LL | x.m()
15+
| ^^^^^ returning this value requires that `'1` must outlive `'static`
16+
17+
error: lifetime may not live long enough
18+
--> $DIR/projection-type-lifetime-mismatch.rs:27:5
19+
|
20+
LL | fn h(x: &()) -> &'static () {
21+
| - let's call the lifetime of this reference `'1`
22+
LL | x.m()
23+
| ^^^^^ returning this value requires that `'1` must outlive `'static`
24+
25+
error: aborting due to 3 previous errors
26+

src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ impl X for () {
1515

1616
fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
1717
x.m()
18-
//~^ ERROR explicit lifetime required
18+
//~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
1919
}
2020

2121
fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
2222
x.m()
23-
//~^ ERROR explicit lifetime required
23+
//~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
2424
}
2525

2626
fn h(x: &()) -> &'static () {
2727
x.m()
28-
//~^ ERROR explicit lifetime required
28+
//~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
2929
}
3030

3131
fn main() {
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1-
error[E0621]: explicit lifetime required in the type of `x`
2-
--> $DIR/projection-type-lifetime-mismatch.rs:17:5
1+
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
2+
--> $DIR/projection-type-lifetime-mismatch.rs:17:7
33
|
4+
LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
5+
| ------------------------------- this data with an anonymous lifetime `'_`...
46
LL | x.m()
5-
| ^^^^^ lifetime `'static` required
7+
| --^-- ...is captured and required to live as long as `'static` here
68

7-
error[E0621]: explicit lifetime required in the type of `x`
8-
--> $DIR/projection-type-lifetime-mismatch.rs:22:5
9+
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
10+
--> $DIR/projection-type-lifetime-mismatch.rs:22:7
911
|
12+
LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
13+
| -- this data with an anonymous lifetime `'_`...
1014
LL | x.m()
11-
| ^^^^^ lifetime `'static` required
15+
| --^-- ...is captured and required to live as long as `'static` here
1216

13-
error[E0621]: explicit lifetime required in the type of `x`
14-
--> $DIR/projection-type-lifetime-mismatch.rs:27:5
17+
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
18+
--> $DIR/projection-type-lifetime-mismatch.rs:27:7
1519
|
20+
LL | fn h(x: &()) -> &'static () {
21+
| --- this data with an anonymous lifetime `'_`...
1622
LL | x.m()
17-
| ^^^^^ lifetime `'static` required
23+
| --^-- ...is captured and required to live as long as `'static` here
1824

1925
error: aborting due to 3 previous errors
2026

21-
For more information about this error, try `rustc --explain E0621`.
27+
For more information about this error, try `rustc --explain E0759`.
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/issue-46983.rs:2:5
3+
|
4+
LL | fn foo(x: &u32) -> &'static u32 {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | &*x
7+
| ^^^ returning this value requires that `'1` must outlive `'static`
8+
9+
error: aborting due to previous error
10+

src/test/ui/issues/issue-46983.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn foo(x: &u32) -> &'static u32 {
22
&*x
3-
//~^ ERROR explicit lifetime required in the type of `x` [E0621]
3+
//~^ ERROR `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
44
}
55

66
fn main() {}

src/test/ui/issues/issue-46983.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
error[E0621]: explicit lifetime required in the type of `x`
1+
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
22
--> $DIR/issue-46983.rs:2:5
33
|
4+
LL | fn foo(x: &u32) -> &'static u32 {
5+
| ---- this data with an anonymous lifetime `'_`...
46
LL | &*x
5-
| ^^^ lifetime `'static` required
7+
| ^^^ ...is captured and required to live as long as `'static` here
68

79
error: aborting due to previous error
810

9-
For more information about this error, try `rustc --explain E0621`.
11+
For more information about this error, try `rustc --explain E0759`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0597]: `foo` does not live long enough
2+
--> $DIR/issue-90600-expected-return-static-indirect.rs:7:32
3+
|
4+
LL | let refcell = RefCell::new(&mut foo);
5+
| ^^^^^^^^ borrowed value does not live long enough
6+
LL |
7+
LL | let read = &refcell as &RefCell<dyn Read>;
8+
| -------- cast requires that `foo` is borrowed for `'static`
9+
...
10+
LL | }
11+
| - `foo` dropped here while still borrowed
12+
13+
error: lifetime may not live long enough
14+
--> $DIR/issue-90600-expected-return-static-indirect.rs:9:16
15+
|
16+
LL | fn inner(mut foo: &[u8]) {
17+
| - let's call the lifetime of this reference `'1`
18+
...
19+
LL | let read = &refcell as &RefCell<dyn Read>;
20+
| ^^^^^^^^ cast requires that `'1` must outlive `'static`
21+
22+
error: aborting due to 2 previous errors
23+
24+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use std::cell::RefCell;
2+
use std::io::Read;
3+
4+
fn main() {}
5+
6+
fn inner(mut foo: &[u8]) {
7+
let refcell = RefCell::new(&mut foo);
8+
//~^ ERROR `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement [E0759]
9+
let read = &refcell as &RefCell<dyn Read>;
10+
11+
read_thing(read);
12+
}
13+
14+
fn read_thing(refcell: &RefCell<dyn Read>) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0759]: `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
2+
--> $DIR/issue-90600-expected-return-static-indirect.rs:7:32
3+
|
4+
LL | fn inner(mut foo: &[u8]) {
5+
| ----- this data with an anonymous lifetime `'_`...
6+
LL | let refcell = RefCell::new(&mut foo);
7+
| ^^^^^^^^ ...is captured here...
8+
...
9+
LL | read_thing(read);
10+
| ---- ...and is required to live as long as `'static` here
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0759`.

src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
fn foo(x: &u32) -> &'static u32 {
99
&*x
10-
//~^ ERROR explicit lifetime required in the type of `x`
10+
//~^ ERROR lifetime may not live long enough
1111
}
1212

1313
fn main() { }

0 commit comments

Comments
 (0)