Skip to content

Commit 27819a0

Browse files
authored
Rollup merge of #142645 - Urgau:usage-non_upper_case_globals, r=fmease
Also emit suggestions for usages in the `non_upper_case_globals` lint This PR adds suggestions for all the usages of the renamed item in the warning of the `non_upper_case_globals` lint. Fixes #124061
2 parents 36b2163 + 6ffd0e6 commit 27819a0

File tree

6 files changed

+252
-15
lines changed

6 files changed

+252
-15
lines changed

compiler/rustc_lint/src/context.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,20 @@ pub trait LintContext {
524524
});
525525
}
526526

527+
/// Emit a lint at `span` from a lazily-constructed lint struct (some type that implements
528+
/// `LintDiagnostic`, typically generated by `#[derive(LintDiagnostic)]`).
529+
fn emit_span_lint_lazy<S: Into<MultiSpan>, L: for<'a> LintDiagnostic<'a, ()>>(
530+
&self,
531+
lint: &'static Lint,
532+
span: S,
533+
decorator: impl FnOnce() -> L,
534+
) {
535+
self.opt_span_lint(lint, Some(span), |lint| {
536+
let decorator = decorator();
537+
decorator.decorate_lint(lint);
538+
});
539+
}
540+
527541
/// Emit a lint at the appropriate level, with an associated span.
528542
///
529543
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature

compiler/rustc_lint/src/lints.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,8 @@ pub(crate) struct NonUpperCaseGlobal<'a> {
13531353
pub name: &'a str,
13541354
#[subdiagnostic]
13551355
pub sub: NonUpperCaseGlobalSub,
1356+
#[subdiagnostic]
1357+
pub usages: Vec<NonUpperCaseGlobalSubTool>,
13561358
}
13571359

13581360
#[derive(Subdiagnostic)]
@@ -1362,14 +1364,29 @@ pub(crate) enum NonUpperCaseGlobalSub {
13621364
#[primary_span]
13631365
span: Span,
13641366
},
1365-
#[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1367+
#[suggestion(lint_suggestion, code = "{replace}")]
13661368
Suggestion {
13671369
#[primary_span]
13681370
span: Span,
1371+
#[applicability]
1372+
applicability: Applicability,
13691373
replace: String,
13701374
},
13711375
}
13721376

1377+
#[derive(Subdiagnostic)]
1378+
#[suggestion(
1379+
lint_suggestion,
1380+
code = "{replace}",
1381+
applicability = "machine-applicable",
1382+
style = "tool-only"
1383+
)]
1384+
pub(crate) struct NonUpperCaseGlobalSubTool {
1385+
#[primary_span]
1386+
pub(crate) span: Span,
1387+
pub(crate) replace: String,
1388+
}
1389+
13731390
// noop_method_call.rs
13741391
#[derive(LintDiagnostic)]
13751392
#[diag(lint_noop_method_call)]

compiler/rustc_lint/src/nonstandard_style.rs

Lines changed: 93 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use rustc_abi::ExternAbi;
22
use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
33
use rustc_attr_parsing::AttributeParser;
4+
use rustc_errors::Applicability;
45
use rustc_hir::def::{DefKind, Res};
5-
use rustc_hir::intravisit::FnKind;
6+
use rustc_hir::def_id::DefId;
7+
use rustc_hir::intravisit::{FnKind, Visitor};
68
use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind};
9+
use rustc_middle::hir::nested_filter::All;
710
use rustc_middle::ty;
811
use rustc_session::config::CrateType;
912
use rustc_session::{declare_lint, declare_lint_pass};
@@ -13,7 +16,7 @@ use {rustc_ast as ast, rustc_hir as hir};
1316

1417
use crate::lints::{
1518
NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub,
16-
NonUpperCaseGlobal, NonUpperCaseGlobalSub,
19+
NonUpperCaseGlobal, NonUpperCaseGlobalSub, NonUpperCaseGlobalSubTool,
1720
};
1821
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
1922

@@ -493,22 +496,82 @@ declare_lint! {
493496
declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
494497

495498
impl NonUpperCaseGlobals {
496-
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
499+
fn check_upper_case(cx: &LateContext<'_>, sort: &str, did: Option<LocalDefId>, ident: &Ident) {
497500
let name = ident.name.as_str();
498501
if name.chars().any(|c| c.is_lowercase()) {
499502
let uc = NonSnakeCase::to_snake_case(name).to_uppercase();
503+
504+
// If the item is exported, suggesting changing it's name would be breaking-change
505+
// and could break users without a "nice" applicable fix, so let's avoid it.
506+
let can_change_usages = if let Some(did) = did {
507+
!cx.tcx.effective_visibilities(()).is_exported(did)
508+
} else {
509+
false
510+
};
511+
500512
// We cannot provide meaningful suggestions
501513
// if the characters are in the category of "Lowercase Letter".
502514
let sub = if *name != uc {
503-
NonUpperCaseGlobalSub::Suggestion { span: ident.span, replace: uc }
515+
NonUpperCaseGlobalSub::Suggestion {
516+
span: ident.span,
517+
replace: uc.clone(),
518+
applicability: if can_change_usages {
519+
Applicability::MachineApplicable
520+
} else {
521+
Applicability::MaybeIncorrect
522+
},
523+
}
504524
} else {
505525
NonUpperCaseGlobalSub::Label { span: ident.span }
506526
};
507-
cx.emit_span_lint(
508-
NON_UPPER_CASE_GLOBALS,
509-
ident.span,
510-
NonUpperCaseGlobal { sort, name, sub },
511-
);
527+
528+
struct UsageCollector<'a, 'tcx> {
529+
cx: &'tcx LateContext<'a>,
530+
did: DefId,
531+
collected: Vec<Span>,
532+
}
533+
534+
impl<'v, 'tcx> Visitor<'v> for UsageCollector<'v, 'tcx> {
535+
type NestedFilter = All;
536+
537+
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
538+
self.cx.tcx
539+
}
540+
541+
fn visit_path(
542+
&mut self,
543+
path: &rustc_hir::Path<'v>,
544+
_id: rustc_hir::HirId,
545+
) -> Self::Result {
546+
if let Some(final_seg) = path.segments.last()
547+
&& final_seg.res.opt_def_id() == Some(self.did)
548+
{
549+
self.collected.push(final_seg.ident.span);
550+
}
551+
}
552+
}
553+
554+
cx.emit_span_lint_lazy(NON_UPPER_CASE_GLOBALS, ident.span, || {
555+
// Compute usages lazily as it can expansive and useless when the lint is allowed.
556+
// cf. https://github.com/rust-lang/rust/pull/142645#issuecomment-2993024625
557+
let usages = if can_change_usages
558+
&& *name != uc
559+
&& let Some(did) = did
560+
{
561+
let mut usage_collector =
562+
UsageCollector { cx, did: did.to_def_id(), collected: Vec::new() };
563+
cx.tcx.hir_walk_toplevel_module(&mut usage_collector);
564+
usage_collector
565+
.collected
566+
.into_iter()
567+
.map(|span| NonUpperCaseGlobalSubTool { span, replace: uc.clone() })
568+
.collect()
569+
} else {
570+
vec![]
571+
};
572+
573+
NonUpperCaseGlobal { sort, name, sub, usages }
574+
});
512575
}
513576
}
514577
}
@@ -520,26 +583,36 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
520583
hir::ItemKind::Static(_, ident, ..)
521584
if !find_attr!(attrs, AttributeKind::NoMangle(..)) =>
522585
{
523-
NonUpperCaseGlobals::check_upper_case(cx, "static variable", &ident);
586+
NonUpperCaseGlobals::check_upper_case(
587+
cx,
588+
"static variable",
589+
Some(it.owner_id.def_id),
590+
&ident,
591+
);
524592
}
525593
hir::ItemKind::Const(ident, ..) => {
526-
NonUpperCaseGlobals::check_upper_case(cx, "constant", &ident);
594+
NonUpperCaseGlobals::check_upper_case(
595+
cx,
596+
"constant",
597+
Some(it.owner_id.def_id),
598+
&ident,
599+
);
527600
}
528601
_ => {}
529602
}
530603
}
531604

532605
fn check_trait_item(&mut self, cx: &LateContext<'_>, ti: &hir::TraitItem<'_>) {
533606
if let hir::TraitItemKind::Const(..) = ti.kind {
534-
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ti.ident);
607+
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ti.ident);
535608
}
536609
}
537610

538611
fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
539612
if let hir::ImplItemKind::Const(..) = ii.kind
540613
&& !assoc_item_in_trait_impl(cx, ii)
541614
{
542-
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
615+
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident);
543616
}
544617
}
545618

@@ -555,6 +628,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
555628
NonUpperCaseGlobals::check_upper_case(
556629
cx,
557630
"constant in pattern",
631+
None,
558632
&segment.ident,
559633
);
560634
}
@@ -564,7 +638,12 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
564638

565639
fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
566640
if let GenericParamKind::Const { .. } = param.kind {
567-
NonUpperCaseGlobals::check_upper_case(cx, "const parameter", &param.name.ident());
641+
NonUpperCaseGlobals::check_upper_case(
642+
cx,
643+
"const parameter",
644+
Some(param.def_id),
645+
&param.name.ident(),
646+
);
568647
}
569648
}
570649
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Checks that the `non_upper_case_globals` emits suggestions for usages as well
2+
// <https://github.com/rust-lang/rust/issues/124061>
3+
4+
//@ check-pass
5+
//@ run-rustfix
6+
7+
#![allow(dead_code)]
8+
9+
use std::cell::Cell;
10+
11+
const MY_STATIC: u32 = 0;
12+
//~^ WARN constant `my_static` should have an upper case name
13+
//~| SUGGESTION MY_STATIC
14+
15+
const LOL: u32 = MY_STATIC + 0;
16+
//~^ SUGGESTION MY_STATIC
17+
18+
mod my_mod {
19+
const INSIDE_MOD: u32 = super::MY_STATIC + 0;
20+
//~^ SUGGESTION MY_STATIC
21+
}
22+
23+
thread_local! {
24+
static FOO_FOO: Cell<usize> = unreachable!();
25+
//~^ WARN constant `fooFOO` should have an upper case name
26+
//~| SUGGESTION FOO_FOO
27+
}
28+
29+
fn foo<const FOO: u32>() {
30+
//~^ WARN const parameter `foo` should have an upper case name
31+
//~| SUGGESTION FOO
32+
let _a = FOO + 1;
33+
//~^ SUGGESTION FOO
34+
}
35+
36+
fn main() {
37+
let _a = crate::MY_STATIC;
38+
//~^ SUGGESTION MY_STATIC
39+
40+
FOO_FOO.set(9);
41+
//~^ SUGGESTION FOO_FOO
42+
println!("{}", FOO_FOO.get());
43+
//~^ SUGGESTION FOO_FOO
44+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Checks that the `non_upper_case_globals` emits suggestions for usages as well
2+
// <https://github.com/rust-lang/rust/issues/124061>
3+
4+
//@ check-pass
5+
//@ run-rustfix
6+
7+
#![allow(dead_code)]
8+
9+
use std::cell::Cell;
10+
11+
const my_static: u32 = 0;
12+
//~^ WARN constant `my_static` should have an upper case name
13+
//~| SUGGESTION MY_STATIC
14+
15+
const LOL: u32 = my_static + 0;
16+
//~^ SUGGESTION MY_STATIC
17+
18+
mod my_mod {
19+
const INSIDE_MOD: u32 = super::my_static + 0;
20+
//~^ SUGGESTION MY_STATIC
21+
}
22+
23+
thread_local! {
24+
static fooFOO: Cell<usize> = unreachable!();
25+
//~^ WARN constant `fooFOO` should have an upper case name
26+
//~| SUGGESTION FOO_FOO
27+
}
28+
29+
fn foo<const foo: u32>() {
30+
//~^ WARN const parameter `foo` should have an upper case name
31+
//~| SUGGESTION FOO
32+
let _a = foo + 1;
33+
//~^ SUGGESTION FOO
34+
}
35+
36+
fn main() {
37+
let _a = crate::my_static;
38+
//~^ SUGGESTION MY_STATIC
39+
40+
fooFOO.set(9);
41+
//~^ SUGGESTION FOO_FOO
42+
println!("{}", fooFOO.get());
43+
//~^ SUGGESTION FOO_FOO
44+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
warning: constant `my_static` should have an upper case name
2+
--> $DIR/lint-non-uppercase-usages.rs:11:7
3+
|
4+
LL | const my_static: u32 = 0;
5+
| ^^^^^^^^^
6+
|
7+
= note: `#[warn(non_upper_case_globals)]` on by default
8+
help: convert the identifier to upper case
9+
|
10+
LL - const my_static: u32 = 0;
11+
LL + const MY_STATIC: u32 = 0;
12+
|
13+
14+
warning: constant `fooFOO` should have an upper case name
15+
--> $DIR/lint-non-uppercase-usages.rs:24:12
16+
|
17+
LL | static fooFOO: Cell<usize> = unreachable!();
18+
| ^^^^^^
19+
|
20+
help: convert the identifier to upper case
21+
|
22+
LL - static fooFOO: Cell<usize> = unreachable!();
23+
LL + static FOO_FOO: Cell<usize> = unreachable!();
24+
|
25+
26+
warning: const parameter `foo` should have an upper case name
27+
--> $DIR/lint-non-uppercase-usages.rs:29:14
28+
|
29+
LL | fn foo<const foo: u32>() {
30+
| ^^^
31+
|
32+
help: convert the identifier to upper case (notice the capitalization difference)
33+
|
34+
LL - fn foo<const foo: u32>() {
35+
LL + fn foo<const FOO: u32>() {
36+
|
37+
38+
warning: 3 warnings emitted
39+

0 commit comments

Comments
 (0)