Skip to content

Commit 6fcb3f3

Browse files
committed
Also emit suggestions for usages in the non_upper_case_globals lint
1 parent 994794a commit 6fcb3f3

File tree

5 files changed

+210
-11
lines changed

5 files changed

+210
-11
lines changed

compiler/rustc_lint/src/lints.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,8 @@ pub(crate) struct NonUpperCaseGlobal<'a> {
13481348
pub name: &'a str,
13491349
#[subdiagnostic]
13501350
pub sub: NonUpperCaseGlobalSub,
1351+
#[subdiagnostic]
1352+
pub usages: Vec<NonUpperCaseGlobalSub>,
13511353
}
13521354

13531355
#[derive(Subdiagnostic)]

compiler/rustc_lint/src/nonstandard_style.rs

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use rustc_abi::ExternAbi;
22
use rustc_attr_data_structures::{AttributeKind, ReprAttr};
33
use rustc_attr_parsing::AttributeParser;
44
use rustc_hir::def::{DefKind, Res};
5-
use rustc_hir::intravisit::FnKind;
5+
use rustc_hir::intravisit::{FnKind, Visitor};
66
use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind};
7+
use rustc_middle::hir::nested_filter::All;
78
use rustc_middle::ty;
89
use rustc_session::config::CrateType;
910
use rustc_session::{declare_lint, declare_lint_pass};
@@ -489,21 +490,59 @@ declare_lint! {
489490
declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
490491

491492
impl NonUpperCaseGlobals {
492-
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
493+
fn check_upper_case(cx: &LateContext<'_>, sort: &str, did: Option<LocalDefId>, ident: &Ident) {
493494
let name = ident.name.as_str();
494495
if name.chars().any(|c| c.is_lowercase()) {
495496
let uc = NonSnakeCase::to_snake_case(name).to_uppercase();
497+
496498
// We cannot provide meaningful suggestions
497499
// if the characters are in the category of "Lowercase Letter".
498-
let sub = if *name != uc {
499-
NonUpperCaseGlobalSub::Suggestion { span: ident.span, replace: uc }
500+
let sub = |span| {
501+
if *name != uc {
502+
NonUpperCaseGlobalSub::Suggestion { span, replace: uc.clone() }
503+
} else {
504+
NonUpperCaseGlobalSub::Label { span }
505+
}
506+
};
507+
508+
struct UsageCollector<'a, 'tcx> {
509+
cx: &'tcx LateContext<'a>,
510+
did: LocalDefId,
511+
collected: Vec<Span>,
512+
}
513+
514+
impl<'v, 'tcx> Visitor<'v> for UsageCollector<'v, 'tcx> {
515+
type NestedFilter = All;
516+
517+
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
518+
self.cx.tcx
519+
}
520+
521+
fn visit_path(
522+
&mut self,
523+
path: &rustc_hir::Path<'v>,
524+
_id: rustc_hir::HirId,
525+
) -> Self::Result {
526+
for seg in path.segments {
527+
if seg.res.opt_def_id() == Some(self.did.to_def_id()) {
528+
self.collected.push(seg.ident.span);
529+
}
530+
}
531+
}
532+
}
533+
534+
let usages = if let Some(did) = did {
535+
let mut usage_collector = UsageCollector { cx, did, collected: Vec::new() };
536+
cx.tcx.hir_walk_toplevel_module(&mut usage_collector);
537+
usage_collector.collected.into_iter().map(|span| sub(span)).collect()
500538
} else {
501-
NonUpperCaseGlobalSub::Label { span: ident.span }
539+
vec![]
502540
};
541+
503542
cx.emit_span_lint(
504543
NON_UPPER_CASE_GLOBALS,
505544
ident.span,
506-
NonUpperCaseGlobal { sort, name, sub },
545+
NonUpperCaseGlobal { sort, name, sub: sub(ident.span), usages },
507546
);
508547
}
509548
}
@@ -516,26 +555,36 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
516555
hir::ItemKind::Static(_, ident, ..)
517556
if !ast::attr::contains_name(attrs, sym::no_mangle) =>
518557
{
519-
NonUpperCaseGlobals::check_upper_case(cx, "static variable", &ident);
558+
NonUpperCaseGlobals::check_upper_case(
559+
cx,
560+
"static variable",
561+
Some(it.owner_id.def_id),
562+
&ident,
563+
);
520564
}
521565
hir::ItemKind::Const(ident, ..) => {
522-
NonUpperCaseGlobals::check_upper_case(cx, "constant", &ident);
566+
NonUpperCaseGlobals::check_upper_case(
567+
cx,
568+
"constant",
569+
Some(it.owner_id.def_id),
570+
&ident,
571+
);
523572
}
524573
_ => {}
525574
}
526575
}
527576

528577
fn check_trait_item(&mut self, cx: &LateContext<'_>, ti: &hir::TraitItem<'_>) {
529578
if let hir::TraitItemKind::Const(..) = ti.kind {
530-
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ti.ident);
579+
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ti.ident);
531580
}
532581
}
533582

534583
fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
535584
if let hir::ImplItemKind::Const(..) = ii.kind
536585
&& !assoc_item_in_trait_impl(cx, ii)
537586
{
538-
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
587+
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident);
539588
}
540589
}
541590

@@ -551,6 +600,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
551600
NonUpperCaseGlobals::check_upper_case(
552601
cx,
553602
"constant in pattern",
603+
None,
554604
&segment.ident,
555605
);
556606
}
@@ -560,7 +610,12 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
560610

561611
fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
562612
if let GenericParamKind::Const { .. } = param.kind {
563-
NonUpperCaseGlobals::check_upper_case(cx, "const parameter", &param.name.ident());
613+
NonUpperCaseGlobals::check_upper_case(
614+
cx,
615+
"const parameter",
616+
Some(param.def_id),
617+
&param.name.ident(),
618+
);
564619
}
565620
}
566621
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
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+
thread_local! {
19+
static FOO_FOO: Cell<usize> = unreachable!();
20+
//~^ WARN constant `fooFOO` should have an upper case name
21+
//~| SUGGESTION FOO_FOO
22+
}
23+
24+
fn foo<const FOO: u32>() {
25+
//~^ WARN const parameter `foo` should have an upper case name
26+
//~| SUGGESTION FOO
27+
let _a = FOO + 1;
28+
//~^ SUGGESTION FOO
29+
}
30+
31+
fn main() {
32+
let _a = crate::MY_STATIC;
33+
//~^ SUGGESTION MY_STATIC
34+
35+
FOO_FOO.set(9);
36+
//~^ SUGGESTION FOO_FOO
37+
println!("{}", FOO_FOO.get());
38+
//~^ SUGGESTION FOO_FOO
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
thread_local! {
19+
static fooFOO: Cell<usize> = unreachable!();
20+
//~^ WARN constant `fooFOO` should have an upper case name
21+
//~| SUGGESTION FOO_FOO
22+
}
23+
24+
fn foo<const foo: u32>() {
25+
//~^ WARN const parameter `foo` should have an upper case name
26+
//~| SUGGESTION FOO
27+
let _a = foo + 1;
28+
//~^ SUGGESTION FOO
29+
}
30+
31+
fn main() {
32+
let _a = crate::my_static;
33+
//~^ SUGGESTION MY_STATIC
34+
35+
fooFOO.set(9);
36+
//~^ SUGGESTION FOO_FOO
37+
println!("{}", fooFOO.get());
38+
//~^ SUGGESTION FOO_FOO
39+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
help: convert the identifier to upper case
14+
|
15+
LL - const LOL: u32 = my_static + 0;
16+
LL + const LOL: u32 = MY_STATIC + 0;
17+
|
18+
help: convert the identifier to upper case
19+
|
20+
LL - let _a = crate::my_static;
21+
LL + let _a = crate::MY_STATIC;
22+
|
23+
24+
warning: constant `fooFOO` should have an upper case name
25+
--> $DIR/lint-non-uppercase-usages.rs:19:12
26+
|
27+
LL | static fooFOO: Cell<usize> = unreachable!();
28+
| ^^^^^^
29+
|
30+
help: convert the identifier to upper case
31+
|
32+
LL - static fooFOO: Cell<usize> = unreachable!();
33+
LL + static FOO_FOO: Cell<usize> = unreachable!();
34+
|
35+
help: convert the identifier to upper case
36+
|
37+
LL - fooFOO.set(9);
38+
LL + FOO_FOO.set(9);
39+
|
40+
help: convert the identifier to upper case
41+
|
42+
LL - println!("{}", fooFOO.get());
43+
LL + println!("{}", FOO_FOO.get());
44+
|
45+
46+
warning: const parameter `foo` should have an upper case name
47+
--> $DIR/lint-non-uppercase-usages.rs:24:14
48+
|
49+
LL | fn foo<const foo: u32>() {
50+
| ^^^
51+
|
52+
help: convert the identifier to upper case (notice the capitalization difference)
53+
|
54+
LL - fn foo<const foo: u32>() {
55+
LL + fn foo<const FOO: u32>() {
56+
|
57+
help: convert the identifier to upper case (notice the capitalization difference)
58+
|
59+
LL - let _a = foo + 1;
60+
LL + let _a = FOO + 1;
61+
|
62+
63+
warning: 3 warnings emitted
64+

0 commit comments

Comments
 (0)