Skip to content

Commit

Permalink
elided_named_lifetimes: add suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
GrigorenkoPV committed Sep 6, 2024
1 parent e38764d commit dcfc713
Show file tree
Hide file tree
Showing 23 changed files with 166 additions and 16 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ lint_elided_named_lifetime = elided lifetime has a name
.label_elided = this elided lifetime gets resolved as `{$name}`
.label_named = lifetime `{$name}` declared here
lint_elided_named_lifetime_suggestion = consider specifying it explicitly
lint_enum_intrinsics_mem_discriminant =
the return value of `mem::discriminant` is unspecified when called with a non-enum type
.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
Expand Down
44 changes: 29 additions & 15 deletions compiler/rustc_lint/src/context/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_errors::{
elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic,
};
use rustc_hir::MissingLifetimeKind;
use rustc_middle::middle::stability;
use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
use rustc_session::Session;
use rustc_span::symbol::kw;
use rustc_span::BytePos;
use tracing::debug;

use crate::lints;
use crate::fluent_generated;
use crate::lints::{self, ElidedNamedLifetime};

mod check_cfg;

Expand Down Expand Up @@ -442,20 +444,32 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
}
BuiltinLintDiag::ElidedNamedLifetimes { elided: (elided, _kind), resolution } => {
match resolution {
ElidedLifetimeResolution::Static => lints::ElidedNamedLifetime {
elided,
name: kw::StaticLifetime,
named_declaration: None,
},
ElidedLifetimeResolution::Param(name, declaration) => lints::ElidedNamedLifetime {
elided,
name,
named_declaration: Some(declaration),
},
}
.decorate_lint(diag)
BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => {
let (name, named_declaration) = match resolution {
ElidedLifetimeResolution::Static => (kw::StaticLifetime, None),
ElidedLifetimeResolution::Param(name, declaration) => (name, Some(declaration)),
};
ElidedNamedLifetime { span, name, named_declaration }.decorate_lint(diag);

let (applicability, suggestion) = match kind {
MissingLifetimeKind::Underscore => {
(Applicability::MachineApplicable, format!("{name}"))
}
MissingLifetimeKind::Ampersand => {
(Applicability::MachineApplicable, format!("&{name} "))
}
MissingLifetimeKind::Comma => (Applicability::Unspecified, format!("<{name}, ")),
MissingLifetimeKind::Brackets => (
Applicability::Unspecified,
format!("{}<{name}>", sess.source_map().span_to_snippet(span).unwrap()),
),
};
diag.span_suggestion_verbose(
span,
fluent_generated::lint_elided_named_lifetime_suggestion,
suggestion,
applicability,
);
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2627,7 +2627,7 @@ pub(crate) struct ElidedLifetimesInPaths {
#[diag(lint_elided_named_lifetime)]
pub(crate) struct ElidedNamedLifetime {
#[label(lint_label_elided)]
pub elided: Span,
pub span: Span,
pub name: Symbol,
#[label(lint_label_named)]
pub named_declaration: Option<Span>,
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/async-await/issues/issue-63388-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ LL | ) -> &dyn Foo
| ^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | ) -> &'a dyn Foo
| ~~~

error[E0621]: explicit lifetime required in the type of `foo`
--> $DIR/issue-63388-1.rs:13:5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target
| ~~~~

warning: 1 warning emitted

4 changes: 4 additions & 0 deletions tests/ui/const-generics/type-dependent/issue-71348.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<'a, N>>::Target
| ~~~~

error: `&'static str` is forbidden as the type of a const generic parameter
--> $DIR/issue-71348.rs:10:24
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/consts/min_const_fn/min_const_fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 }
| ^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | const fn get_lt(&'a self) -> &'a T { &self.0 }
| ~~~

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

error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time
--> $DIR/min_const_fn.rs:37:25
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
| ~~

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/impl-fn-hrtb-bounds.rs:4:41
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {
| ~~

error[E0792]: expected generic lifetime parameter, found `'_`
--> $DIR/impl-fn-predefined-lifetimes.rs:7:9
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item =
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &'a u32)> {
| ~~~

warning: 1 warning emitted

Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" }
| lifetime `'a` declared here
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" }
| ~~~

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 {
| lifetime `'a` declared here
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 {
| ~~~

error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ note: the lint level is defined here
|
LL | #![deny(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider specifying it explicitly
|
LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 {
| ~~~~~~~~

error: aborting due to 1 previous error

19 changes: 19 additions & 0 deletions tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ note: the lint level is defined here
|
LL | #![deny(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider specifying it explicitly
|
LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 {
| ~~~

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

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

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

error: aborting due to 4 previous errors

8 changes: 8 additions & 0 deletions tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ note: the lint level is defined here
|
LL | #[warn(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider specifying it explicitly
|
LL | fn bar(x: &'static u8) -> &'static u8 {
| ~~~~~~~~

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

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

19 changes: 19 additions & 0 deletions tests/ui/lint/elided-named-lifetimes/static.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,43 @@ note: the lint level is defined here
|
LL | #![deny(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider specifying it explicitly
|
LL | fn ampersand(x: &'static u8) -> &'static u8 {
| ~~~~~~~~

error: elided lifetime has a name
--> $DIR/static.rs:23:32
|
LL | fn brackets(x: &'static u8) -> Brackets {
| ^^^^^^^^ this elided lifetime gets resolved as `'static`
|
help: consider specifying it explicitly
|
LL | fn brackets(x: &'static u8) -> Brackets<'static> {
| ~~~~~~~~~~~~~~~~~

error: elided lifetime has a name
--> $DIR/static.rs:30:34
|
LL | fn comma(x: &'static u8) -> Comma<u8> {
| ^ this elided lifetime gets resolved as `'static`
|
help: consider specifying it explicitly
|
LL | fn comma(x: &'static u8) -> Comma<'static, u8> {
| ~~~~~~~~~

error: elided lifetime has a name
--> $DIR/static.rs:35:35
|
LL | fn underscore(x: &'static u8) -> &'_ u8 {
| ^^ this elided lifetime gets resolved as `'static`
|
help: consider specifying it explicitly
|
LL | fn underscore(x: &'static u8) -> &'static u8 {
| ~~~~~~~

error: aborting due to 4 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait {
| lifetime `'a` declared here
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait {
| ~~~

error: lifetime may not live long enough
--> $DIR/object-lifetime-default-elision.rs:73:5
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str {
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn a<'a>(self: Self, a: &'a str) -> &'a str {
| ~~~

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

warning: 2 warnings emitted

9 changes: 9 additions & 0 deletions tests/ui/self/self_lifetime-async.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
| lifetime `'b` declared here
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 }
| ~~~

warning: elided lifetime has a name
--> $DIR/self_lifetime-async.rs:12:52
|
LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
help: consider specifying it explicitly
|
LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg }
| ~~~

warning: 2 warnings emitted

9 changes: 9 additions & 0 deletions tests/ui/self/self_lifetime.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
| lifetime `'b` declared here
|
= note: `#[warn(elided_named_lifetimes)]` on by default
help: consider specifying it explicitly
|
LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 }
| ~~~

warning: elided lifetime has a name
--> $DIR/self_lifetime.rs:13:46
|
LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
help: consider specifying it explicitly
|
LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg }
| ~~~

warning: 2 warnings emitted

Loading

0 comments on commit dcfc713

Please sign in to comment.