Skip to content

Commit 80733c0

Browse files
committed
elided_named_lifetimes: add suggestions
1 parent db61426 commit 80733c0

23 files changed

+166
-16
lines changed

compiler/rustc_lint/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ lint_elided_named_lifetime = elided lifetime has a name
256256
.label_elided = this elided lifetime gets resolved as `{$name}`
257257
.label_named = lifetime `{$name}` declared here
258258
259+
lint_elided_named_lifetime_suggestion = consider specifying it explicitly
260+
259261
lint_enum_intrinsics_mem_discriminant =
260262
the return value of `mem::discriminant` is unspecified when called with a non-enum type
261263
.note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum

compiler/rustc_lint/src/context/diagnostics.rs

+29-15
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
77
use rustc_errors::{
88
elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic,
99
};
10+
use rustc_hir::MissingLifetimeKind;
1011
use rustc_middle::middle::stability;
1112
use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
1213
use rustc_session::Session;
1314
use rustc_span::symbol::kw;
1415
use rustc_span::BytePos;
1516
use tracing::debug;
1617

17-
use crate::lints;
18+
use crate::fluent_generated;
19+
use crate::lints::{self, ElidedNamedLifetime};
1820

1921
mod check_cfg;
2022

@@ -442,20 +444,32 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
442444
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
443445
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
444446
}
445-
BuiltinLintDiag::ElidedNamedLifetimes { elided: (elided, _kind), resolution } => {
446-
match resolution {
447-
ElidedLifetimeResolution::Static => lints::ElidedNamedLifetime {
448-
elided,
449-
name: kw::StaticLifetime,
450-
named_declaration: None,
451-
},
452-
ElidedLifetimeResolution::Param(name, declaration) => lints::ElidedNamedLifetime {
453-
elided,
454-
name,
455-
named_declaration: Some(declaration),
456-
},
457-
}
458-
.decorate_lint(diag)
447+
BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => {
448+
let (name, named_declaration) = match resolution {
449+
ElidedLifetimeResolution::Static => (kw::StaticLifetime, None),
450+
ElidedLifetimeResolution::Param(name, declaration) => (name, Some(declaration)),
451+
};
452+
ElidedNamedLifetime { span, name, named_declaration }.decorate_lint(diag);
453+
454+
let (applicability, suggestion) = match kind {
455+
MissingLifetimeKind::Underscore => {
456+
(Applicability::MachineApplicable, format!("{name}"))
457+
}
458+
MissingLifetimeKind::Ampersand => {
459+
(Applicability::MachineApplicable, format!("&{name} "))
460+
}
461+
MissingLifetimeKind::Comma => (Applicability::Unspecified, format!("<{name}, ")),
462+
MissingLifetimeKind::Brackets => (
463+
Applicability::Unspecified,
464+
format!("{}<{name}>", sess.source_map().span_to_snippet(span).unwrap()),
465+
),
466+
};
467+
diag.span_suggestion_verbose(
468+
span,
469+
fluent_generated::lint_elided_named_lifetime_suggestion,
470+
suggestion,
471+
applicability,
472+
);
459473
}
460474
}
461475
}

compiler/rustc_lint/src/lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2615,7 +2615,7 @@ pub(crate) struct ElidedLifetimesInPaths {
26152615
#[diag(lint_elided_named_lifetime)]
26162616
pub(crate) struct ElidedNamedLifetime {
26172617
#[label(lint_label_elided)]
2618-
pub elided: Span,
2618+
pub span: Span,
26192619
pub name: Symbol,
26202620
#[label(lint_label_named)]
26212621
pub named_declaration: Option<Span>,

tests/ui/async-await/issues/issue-63388-1.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | ) -> &dyn Foo
88
| ^ this elided lifetime gets resolved as `'a`
99
|
1010
= note: `#[warn(elided_named_lifetimes)]` on by default
11+
help: consider specifying it explicitly
12+
|
13+
LL | ) -> &'a dyn Foo
14+
| ~~~
1115

1216
error[E0621]: explicit lifetime required in the type of `foo`
1317
--> $DIR/issue-63388-1.rs:13:5

tests/ui/const-generics/type-dependent/issue-71348.full.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
55
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
66
|
77
= note: `#[warn(elided_named_lifetimes)]` on by default
8+
help: consider specifying it explicitly
9+
|
10+
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target
11+
| ~~~~
812

913
warning: 1 warning emitted
1014

tests/ui/const-generics/type-dependent/issue-71348.min.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
55
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
66
|
77
= note: `#[warn(elided_named_lifetimes)]` on by default
8+
help: consider specifying it explicitly
9+
|
10+
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target
11+
| ~~~~
812

913
error: `&'static str` is forbidden as the type of a const generic parameter
1014
--> $DIR/issue-71348.rs:10:24

tests/ui/consts/min_const_fn/min_const_fn.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 }
88
| ^ this elided lifetime gets resolved as `'a`
99
|
1010
= note: `#[warn(elided_named_lifetimes)]` on by default
11+
help: consider specifying it explicitly
12+
|
13+
LL | const fn get_lt(&'a self) -> &'a T { &self.0 }
14+
| ~~~
1115

1216
warning: elided lifetime has a name
1317
--> $DIR/min_const_fn.rs:48:42
@@ -17,6 +21,11 @@ LL | impl<'a, T> Foo<T> {
1721
...
1822
LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
1923
| ^ this elided lifetime gets resolved as `'a`
24+
|
25+
help: consider specifying it explicitly
26+
|
27+
LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 }
28+
| ~~~
2029

2130
error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time
2231
--> $DIR/min_const_fn.rs:37:25

tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
1717
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
1818
|
1919
= note: `#[warn(elided_named_lifetimes)]` on by default
20+
help: consider specifying it explicitly
21+
|
22+
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
23+
| ~~
2024

2125
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
2226
--> $DIR/impl-fn-hrtb-bounds.rs:4:41

tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
55
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
66
|
77
= note: `#[warn(elided_named_lifetimes)]` on by default
8+
help: consider specifying it explicitly
9+
|
10+
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {
11+
| ~~
812

913
error[E0792]: expected generic lifetime parameter, found `'_`
1014
--> $DIR/impl-fn-predefined-lifetimes.rs:7:9

tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item =
55
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
66
|
77
= note: `#[warn(elided_named_lifetimes)]` on by default
8+
help: consider specifying it explicitly
9+
|
10+
LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &'a u32)> {
11+
| ~~~
812

913
warning: 1 warning emitted
1014

tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" }
114114
| lifetime `'a` declared here
115115
|
116116
= note: `#[warn(elided_named_lifetimes)]` on by default
117+
help: consider specifying it explicitly
118+
|
119+
LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" }
120+
| ~~~
117121

118122
error: aborting due to 7 previous errors; 1 warning emitted
119123

tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 {
77
| lifetime `'a` declared here
88
|
99
= note: `#[warn(elided_named_lifetimes)]` on by default
10+
help: consider specifying it explicitly
11+
|
12+
LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 {
13+
| ~~~
1014

1115
error[E0621]: explicit lifetime required in the type of `x`
1216
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36

tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ note: the lint level is defined here
99
|
1010
LL | #![deny(elided_named_lifetimes)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^
12+
help: consider specifying it explicitly
13+
|
14+
LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 {
15+
| ~~~~~~~~
1216

1317
error: aborting due to 1 previous error
1418

tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr

+19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ note: the lint level is defined here
1111
|
1212
LL | #![deny(elided_named_lifetimes)]
1313
| ^^^^^^^^^^^^^^^^^^^^^^
14+
help: consider specifying it explicitly
15+
|
16+
LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 {
17+
| ~~~
1418

1519
error: elided lifetime has a name
1620
--> $DIR/missing-lifetime-kind.rs:10:31
@@ -19,6 +23,11 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets {
1923
| -- ^^^^^^^^ this elided lifetime gets resolved as `'a`
2024
| |
2125
| lifetime `'a` declared here
26+
|
27+
help: consider specifying it explicitly
28+
|
29+
LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> {
30+
| ~~~~~~~~~~~~
2231

2332
error: elided lifetime has a name
2433
--> $DIR/missing-lifetime-kind.rs:17:33
@@ -27,6 +36,11 @@ LL | fn comma<'a>(x: &'a u8) -> Comma<u8> {
2736
| -- ^ this elided lifetime gets resolved as `'a`
2837
| |
2938
| lifetime `'a` declared here
39+
|
40+
help: consider specifying it explicitly
41+
|
42+
LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> {
43+
| ~~~~
3044

3145
error: elided lifetime has a name
3246
--> $DIR/missing-lifetime-kind.rs:22:34
@@ -35,6 +49,11 @@ LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 {
3549
| -- ^^ this elided lifetime gets resolved as `'a`
3650
| |
3751
| lifetime `'a` declared here
52+
|
53+
help: consider specifying it explicitly
54+
|
55+
LL | fn underscore<'a>(x: &'a u8) -> &'a u8 {
56+
| ~~
3857

3958
error: aborting due to 4 previous errors
4059

tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ note: the lint level is defined here
99
|
1010
LL | #[warn(elided_named_lifetimes)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^
12+
help: consider specifying it explicitly
13+
|
14+
LL | fn bar(x: &'static u8) -> &'static u8 {
15+
| ~~~~~~~~
1216

1317
error: elided lifetime has a name
1418
--> $DIR/not-tied-to-crate.rs:11:31
@@ -21,6 +25,10 @@ note: the lint level is defined here
2125
|
2226
LL | #[deny(elided_named_lifetimes)]
2327
| ^^^^^^^^^^^^^^^^^^^^^^
28+
help: consider specifying it explicitly
29+
|
30+
LL | fn baz(x: &'static u8) -> &'static u8 {
31+
| ~~~~~~~~
2432

2533
error: aborting due to 1 previous error; 1 warning emitted
2634

tests/ui/lint/elided-named-lifetimes/static.stderr

+19
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,43 @@ note: the lint level is defined here
99
|
1010
LL | #![deny(elided_named_lifetimes)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^
12+
help: consider specifying it explicitly
13+
|
14+
LL | fn ampersand(x: &'static u8) -> &'static u8 {
15+
| ~~~~~~~~
1216

1317
error: elided lifetime has a name
1418
--> $DIR/static.rs:23:32
1519
|
1620
LL | fn brackets(x: &'static u8) -> Brackets {
1721
| ^^^^^^^^ this elided lifetime gets resolved as `'static`
22+
|
23+
help: consider specifying it explicitly
24+
|
25+
LL | fn brackets(x: &'static u8) -> Brackets<'static> {
26+
| ~~~~~~~~~~~~~~~~~
1827

1928
error: elided lifetime has a name
2029
--> $DIR/static.rs:30:34
2130
|
2231
LL | fn comma(x: &'static u8) -> Comma<u8> {
2332
| ^ this elided lifetime gets resolved as `'static`
33+
|
34+
help: consider specifying it explicitly
35+
|
36+
LL | fn comma(x: &'static u8) -> Comma<'static, u8> {
37+
| ~~~~~~~~~
2438

2539
error: elided lifetime has a name
2640
--> $DIR/static.rs:35:35
2741
|
2842
LL | fn underscore(x: &'static u8) -> &'_ u8 {
2943
| ^^ this elided lifetime gets resolved as `'static`
44+
|
45+
help: consider specifying it explicitly
46+
|
47+
LL | fn underscore(x: &'static u8) -> &'static u8 {
48+
| ~~~~~~~
3049

3150
error: aborting due to 4 previous errors
3251

tests/ui/object-lifetime/object-lifetime-default-elision.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait {
77
| lifetime `'a` declared here
88
|
99
= note: `#[warn(elided_named_lifetimes)]` on by default
10+
help: consider specifying it explicitly
11+
|
12+
LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait {
13+
| ~~~
1014

1115
error: lifetime may not live long enough
1216
--> $DIR/object-lifetime-default-elision.rs:73:5

tests/ui/self/elision/ignore-non-reference-lifetimes.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,21 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str {
55
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
66
|
77
= note: `#[warn(elided_named_lifetimes)]` on by default
8+
help: consider specifying it explicitly
9+
|
10+
LL | fn a<'a>(self: Self, a: &'a str) -> &'a str {
11+
| ~~~
812

913
warning: elided lifetime has a name
1014
--> $DIR/ignore-non-reference-lifetimes.rs:10:44
1115
|
1216
LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str {
1317
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
18+
|
19+
help: consider specifying it explicitly
20+
|
21+
LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str {
22+
| ~~~
1423

1524
warning: 2 warnings emitted
1625

tests/ui/self/self_lifetime-async.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,21 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
77
| lifetime `'b` declared here
88
|
99
= note: `#[warn(elided_named_lifetimes)]` on by default
10+
help: consider specifying it explicitly
11+
|
12+
LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 }
13+
| ~~~
1014

1115
warning: elided lifetime has a name
1216
--> $DIR/self_lifetime-async.rs:12:52
1317
|
1418
LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
1519
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
20+
|
21+
help: consider specifying it explicitly
22+
|
23+
LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg }
24+
| ~~~
1625

1726
warning: 2 warnings emitted
1827

tests/ui/self/self_lifetime.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,21 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
77
| lifetime `'b` declared here
88
|
99
= note: `#[warn(elided_named_lifetimes)]` on by default
10+
help: consider specifying it explicitly
11+
|
12+
LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 }
13+
| ~~~
1014

1115
warning: elided lifetime has a name
1216
--> $DIR/self_lifetime.rs:13:46
1317
|
1418
LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
1519
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
20+
|
21+
help: consider specifying it explicitly
22+
|
23+
LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg }
24+
| ~~~
1625

1726
warning: 2 warnings emitted
1827

0 commit comments

Comments
 (0)