Skip to content

Commit 9174d9f

Browse files
committed
WIP
1 parent db63611 commit 9174d9f

28 files changed

+247
-331
lines changed

compiler/rustc_hir/src/def.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -829,12 +829,7 @@ pub enum LifetimeRes {
829829
/// late resolution. Those lifetimes will be inferred by typechecking.
830830
Infer,
831831
/// `'static` lifetime.
832-
Static {
833-
/// We do not want to emit `elided_named_lifetimes`
834-
/// when we are inside of a const item or a static,
835-
/// because it would get too annoying.
836-
suppress_elision_warning: bool,
837-
},
832+
Static,
838833
/// Resolution failure.
839834
Error,
840835
/// HACK: This is used to recover the NodeId of an elided lifetime.

compiler/rustc_lint/src/context/diagnostics.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ use rustc_errors::{
88
elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic,
99
};
1010
use rustc_middle::middle::stability;
11-
use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
11+
use rustc_session::lint::BuiltinLintDiag;
1212
use rustc_session::Session;
13-
use rustc_span::symbol::kw;
1413
use rustc_span::BytePos;
1514
use tracing::debug;
1615

17-
use crate::lints::{self, ElidedNamedLifetime};
16+
use crate::lints::{self};
1817

1918
mod check_cfg;
2019

@@ -446,16 +445,5 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
446445
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
447446
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
448447
}
449-
BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => {
450-
match resolution {
451-
ElidedLifetimeResolution::Static => {
452-
ElidedNamedLifetime { span, kind, name: kw::StaticLifetime, declaration: None }
453-
}
454-
ElidedLifetimeResolution::Param(name, declaration) => {
455-
ElidedNamedLifetime { span, kind, name, declaration: Some(declaration) }
456-
}
457-
}
458-
.decorate_lint(diag)
459-
}
460448
}
461449
}

compiler/rustc_lint/src/elided.rs

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use rustc_hir::def_id::LocalDefId;
2+
use rustc_hir::intravisit::{walk_fn_decl, FnKind, Visitor};
3+
use rustc_hir::{
4+
Body, FnDecl, FnSig, ImplItem, ImplItemKind, Lifetime, LifetimeName, TraitItem, TraitItemKind,
5+
};
6+
use rustc_middle::ty::layout::HasTyCtxt;
7+
use rustc_session::{declare_lint, declare_lint_pass};
8+
use rustc_span::symbol::kw;
9+
use rustc_span::Span;
10+
11+
use crate::lints::{ElidedNamedLifetime, ElidedNamedLifetimeSuggestion};
12+
use crate::{LateContext, LateLintPass, LintContext};
13+
14+
declare_lint! {
15+
/// The `elided_named_lifetimes` lint detects when an elided
16+
/// lifetime ends up being a named lifetime, such as `'static`
17+
/// or some lifetime parameter `'a`.
18+
///
19+
/// ### Example
20+
///
21+
/// ```rust,compile_fail
22+
/// #![deny(elided_named_lifetimes)]
23+
/// struct Foo;
24+
/// impl Foo {
25+
/// pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
26+
/// unsafe { &mut *(x as *mut _) }
27+
/// }
28+
/// }
29+
/// ```
30+
///
31+
/// {{produces}}
32+
///
33+
/// ### Explanation
34+
///
35+
/// Lifetime elision is quite useful, because it frees you from having
36+
/// to give each lifetime its own name, but sometimes it can produce
37+
/// somewhat surprising resolutions. In safe code, it is mostly okay,
38+
/// because the borrow checker prevents any unsoundness, so the worst
39+
/// case scenario is you get a confusing error message in some other place.
40+
/// But with `unsafe` code, such unexpected resolutions may lead to unsound code.
41+
pub ELIDED_NAMED_LIFETIMES,
42+
Warn,
43+
"detects when an elided lifetime gets resolved to be `'static` or some named parameter"
44+
}
45+
46+
declare_lint_pass!(ElidedNamedLifetimes => [ELIDED_NAMED_LIFETIMES]);
47+
48+
impl<'tcx> LateLintPass<'tcx> for ElidedNamedLifetimes {
49+
fn check_fn(
50+
&mut self,
51+
cx: &LateContext<'tcx>,
52+
_: FnKind<'tcx>,
53+
decl: &'tcx FnDecl<'tcx>,
54+
_: &'tcx Body<'tcx>,
55+
_: Span,
56+
_: LocalDefId,
57+
) {
58+
self.check_decl(cx, decl)
59+
}
60+
61+
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) {
62+
if let TraitItemKind::Fn(FnSig { decl, .. }, _) = item.kind {
63+
self.check_decl(cx, decl)
64+
}
65+
}
66+
67+
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
68+
if let ImplItemKind::Fn(FnSig { decl, .. }, _) = item.kind {
69+
self.check_decl(cx, decl)
70+
}
71+
}
72+
}
73+
74+
impl ElidedNamedLifetimes {
75+
fn check_decl<'tcx>(&self, cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'tcx>) {
76+
walk_fn_decl(&mut LifetimeVisitor { cx }, decl)
77+
}
78+
}
79+
struct LifetimeVisitor<'a, 'tcx> {
80+
cx: &'a LateContext<'tcx>,
81+
}
82+
83+
impl<'tcx> Visitor<'tcx> for LifetimeVisitor<'_, 'tcx> {
84+
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) -> Self::Result {
85+
// `.is_elided()` should probably be called `.resolves_to_elided()`,
86+
// and `.is_anonymous()` is actually the thing that we need here.
87+
if !lifetime.is_anonymous() {
88+
return;
89+
}
90+
let (name, declaration) = match lifetime.res {
91+
LifetimeName::Param(param) => {
92+
let tcx = self.cx.tcx();
93+
let name = tcx.item_name(param.into());
94+
if name == kw::UnderscoreLifetime {
95+
return;
96+
}
97+
let span = tcx.source_span(param);
98+
(name, Some(span))
99+
}
100+
LifetimeName::Static => (kw::StaticLifetime, None),
101+
LifetimeName::ImplicitObjectLifetimeDefault
102+
| LifetimeName::Error
103+
| LifetimeName::Infer => return,
104+
};
105+
self.cx.emit_lint(
106+
ELIDED_NAMED_LIFETIMES,
107+
ElidedNamedLifetime {
108+
span: lifetime.ident.span,
109+
sugg: {
110+
let (span, code) = lifetime.suggestion();
111+
ElidedNamedLifetimeSuggestion { span, code }
112+
},
113+
name,
114+
declaration,
115+
},
116+
)
117+
}
118+
}

compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ mod context;
5050
mod deref_into_dyn_supertrait;
5151
mod drop_forget_useless;
5252
mod early;
53+
mod elided;
5354
mod enum_intrinsics_non_enums;
5455
mod errors;
5556
mod expect;
@@ -91,6 +92,7 @@ use async_fn_in_trait::AsyncFnInTrait;
9192
use builtin::*;
9293
use deref_into_dyn_supertrait::*;
9394
use drop_forget_useless::*;
95+
use elided::ElidedNamedLifetimes;
9496
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
9597
use for_loops_over_fallibles::*;
9698
use hidden_unicode_codepoints::*;
@@ -243,6 +245,7 @@ late_lint_methods!(
243245
NonLocalDefinitions: NonLocalDefinitions::default(),
244246
ImplTraitOvercaptures: ImplTraitOvercaptures,
245247
TailExprDropOrder: TailExprDropOrder,
248+
ElidedNamedLifetimes: ElidedNamedLifetimes,
246249
]
247250
]
248251
);

compiler/rustc_lint/src/lints.rs

+16-29
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_errors::{
99
};
1010
use rustc_hir::def::Namespace;
1111
use rustc_hir::def_id::DefId;
12-
use rustc_hir::{self as hir, MissingLifetimeKind};
12+
use rustc_hir::{self as hir, LifetimeSuggestionPosition};
1313
use rustc_macros::{LintDiagnostic, Subdiagnostic};
1414
use rustc_middle::ty::inhabitedness::InhabitedPredicate;
1515
use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
@@ -2624,16 +2624,23 @@ pub(crate) struct ElidedLifetimesInPaths {
26242624
pub subdiag: ElidedLifetimeInPathSubdiag,
26252625
}
26262626

2627+
#[allow(unused)]
26272628
pub(crate) struct ElidedNamedLifetime {
26282629
pub span: Span,
2629-
pub kind: MissingLifetimeKind,
26302630
pub name: Symbol,
26312631
pub declaration: Option<Span>,
2632+
pub sugg: ElidedNamedLifetimeSuggestion,
2633+
}
2634+
2635+
pub(crate) struct ElidedNamedLifetimeSuggestion {
2636+
pub span: Span,
2637+
pub code: String,
26322638
}
26332639

26342640
impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime {
26352641
fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) {
2636-
let Self { span, kind, name, declaration } = self;
2642+
let Self { span, name, declaration, sugg } = self;
2643+
diag.span(span);
26372644
diag.primary_message(fluent::lint_elided_named_lifetime);
26382645
diag.arg("name", name);
26392646
diag.span_label(span, fluent::lint_label_elided);
@@ -2647,32 +2654,12 @@ impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime {
26472654
if name != rustc_span::symbol::kw::StaticLifetime {
26482655
return;
26492656
}
2650-
match kind {
2651-
MissingLifetimeKind::Underscore => diag.span_suggestion_verbose(
2652-
span,
2653-
fluent::lint_suggestion,
2654-
format!("{name}"),
2655-
Applicability::MachineApplicable,
2656-
),
2657-
MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose(
2658-
span.shrink_to_hi(),
2659-
fluent::lint_suggestion,
2660-
format!("{name} "),
2661-
Applicability::MachineApplicable,
2662-
),
2663-
MissingLifetimeKind::Comma => diag.span_suggestion_verbose(
2664-
span.shrink_to_hi(),
2665-
fluent::lint_suggestion,
2666-
format!("{name}, "),
2667-
Applicability::MachineApplicable,
2668-
),
2669-
MissingLifetimeKind::Brackets => diag.span_suggestion_verbose(
2670-
span.shrink_to_hi(),
2671-
fluent::lint_suggestion,
2672-
format!("<{name}>"),
2673-
Applicability::MachineApplicable,
2674-
),
2675-
};
2657+
diag.span_suggestion_verbose(
2658+
sugg.span,
2659+
fluent::lint_suggestion,
2660+
sugg.code,
2661+
Applicability::MachineApplicable,
2662+
);
26762663
}
26772664
}
26782665

compiler/rustc_lint_defs/src/builtin.rs

-33
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ declare_lint_pass! {
4242
DUPLICATE_MACRO_ATTRIBUTES,
4343
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4444
ELIDED_LIFETIMES_IN_PATHS,
45-
ELIDED_NAMED_LIFETIMES,
4645
EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
4746
EXPORTED_PRIVATE_DEPENDENCIES,
4847
FFI_UNWIND_CALLS,
@@ -1863,38 +1862,6 @@ declare_lint! {
18631862
"hidden lifetime parameters in types are deprecated"
18641863
}
18651864

1866-
declare_lint! {
1867-
/// The `elided_named_lifetimes` lint detects when an elided
1868-
/// lifetime ends up being a named lifetime, such as `'static`
1869-
/// or some lifetime parameter `'a`.
1870-
///
1871-
/// ### Example
1872-
///
1873-
/// ```rust,compile_fail
1874-
/// #![deny(elided_named_lifetimes)]
1875-
/// struct Foo;
1876-
/// impl Foo {
1877-
/// pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
1878-
/// unsafe { &mut *(x as *mut _) }
1879-
/// }
1880-
/// }
1881-
/// ```
1882-
///
1883-
/// {{produces}}
1884-
///
1885-
/// ### Explanation
1886-
///
1887-
/// Lifetime elision is quite useful, because it frees you from having
1888-
/// to give each lifetime its own name, but sometimes it can produce
1889-
/// somewhat surprising resolutions. In safe code, it is mostly okay,
1890-
/// because the borrow checker prevents any unsoundness, so the worst
1891-
/// case scenario is you get a confusing error message in some other place.
1892-
/// But with `unsafe` code, such unexpected resolutions may lead to unsound code.
1893-
pub ELIDED_NAMED_LIFETIMES,
1894-
Warn,
1895-
"detects when an elided lifetime gets resolved to be `'static` or some named parameter"
1896-
}
1897-
18981865
declare_lint! {
18991866
/// The `bare_trait_objects` lint suggests using `dyn Trait` for trait
19001867
/// objects.

compiler/rustc_lint_defs/src/lib.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{
1010
};
1111
use rustc_error_messages::{DiagMessage, MultiSpan};
1212
use rustc_hir::def::Namespace;
13-
use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
13+
use rustc_hir::{HashStableContext, HirId};
1414
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
1515
use rustc_span::edition::Edition;
1616
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
@@ -556,12 +556,6 @@ pub enum DeprecatedSinceKind {
556556
InVersion(String),
557557
}
558558

559-
#[derive(Debug)]
560-
pub enum ElidedLifetimeResolution {
561-
Static,
562-
Param(Symbol, Span),
563-
}
564-
565559
// This could be a closure, but then implementing derive trait
566560
// becomes hacky (and it gets allocated).
567561
#[derive(Debug)]
@@ -574,10 +568,6 @@ pub enum BuiltinLintDiag {
574568
},
575569
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
576570
ElidedLifetimesInPaths(usize, Span, bool, Span),
577-
ElidedNamedLifetimes {
578-
elided: (Span, MissingLifetimeKind),
579-
resolution: ElidedLifetimeResolution,
580-
},
581571
UnknownCrateTypes {
582572
span: Span,
583573
candidate: Option<Symbol>,

0 commit comments

Comments
 (0)