1use rustc_abi::ExternAbi;
2use rustc_ast as ast;
3use rustc_attr_parsing::AttributeParser;
4use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level};
5use rustc_hir as hir;
6use rustc_hir::attrs::{AttributeKind, ReprAttr};
7use rustc_hir::def::{DefKind, Res};
8use rustc_hir::def_id::DefId;
9use rustc_hir::intravisit::{FnKind, Visitor};
10use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
11use rustc_middle::hir::nested_filter::All;
12use rustc_middle::ty::AssocContainer;
13use rustc_session::config::CrateType;
14use rustc_session::{declare_lint, declare_lint_pass};
15use rustc_span::def_id::LocalDefId;
16use rustc_span::{BytePos, Ident, Span, sym};
17
18use crate::lints::{
19 NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub,
20 NonUpperCaseGlobal, NonUpperCaseGlobalSub, NonUpperCaseGlobalSubTool,
21};
22use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
23
24#[doc =
r" The `non_camel_case_types` lint detects types, variants, traits and"]
#[doc = r" type parameters that don't have camel case names."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" struct my_struct;"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r#" The preferred style for these identifiers is to use "camel case", such"#]
#[doc =
r" as `MyStruct`, where the first letter should not be lowercase, and"]
#[doc =
r" should not use underscores between letters. Underscores are allowed at"]
#[doc = r" the beginning and end of the identifier, as well as between"]
#[doc = r" non-letters (such as `X86_64`)."]
pub static NON_CAMEL_CASE_TYPES: &::rustc_lint_defs::Lint =
&::rustc_lint_defs::Lint {
name: "NON_CAMEL_CASE_TYPES",
default_level: ::rustc_lint_defs::Warn,
desc: "types, variants, traits and type parameters should have camel case names",
is_externally_loaded: false,
..::rustc_lint_defs::Lint::default_fields_for_macro()
};declare_lint! {
25 pub NON_CAMEL_CASE_TYPES,
44 Warn,
45 "types, variants, traits and type parameters should have camel case names"
46}
47
48pub struct NonCamelCaseTypes;
#[automatically_derived]
impl ::core::marker::Copy for NonCamelCaseTypes { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for NonCamelCaseTypes { }
#[automatically_derived]
impl ::core::clone::Clone for NonCamelCaseTypes {
#[inline]
fn clone(&self) -> NonCamelCaseTypes { *self }
}
impl ::rustc_lint_defs::LintPass for NonCamelCaseTypes {
fn name(&self) -> &'static str { "NonCamelCaseTypes" }
fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[NON_CAMEL_CASE_TYPES]))
}
}
impl NonCamelCaseTypes {
#[allow(unused)]
pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[NON_CAMEL_CASE_TYPES]))
}
}declare_lint_pass!(NonCamelCaseTypes => [NON_CAMEL_CASE_TYPES]);
49
50fn char_has_case(c: char) -> bool {
54 let mut l = c.to_lowercase();
55 let mut u = c.to_uppercase();
56 while let Some(l) = l.next() {
57 match u.next() {
58 Some(u) if l != u => return true,
59 _ => {}
60 }
61 }
62 u.next().is_some()
63}
64
65fn is_camel_case(name: &str) -> bool {
66 let name = name.trim_matches('_');
67 if name.is_empty() {
68 return true;
69 }
70
71 !name.chars().next().unwrap().is_lowercase()
74 && !name.contains("__")
75 && !name.chars().collect::<Vec<_>>().array_windows().any(|&[fst, snd]| {
76 char_has_case(fst) && snd == '_' || char_has_case(snd) && fst == '_'
78 })
79}
80
81fn to_camel_case(s: &str) -> String {
82 s.trim_matches('_')
83 .split('_')
84 .filter(|component| !component.is_empty())
85 .map(|component| {
86 let mut camel_cased_component = String::new();
87
88 let mut new_word = true;
89 let mut prev_is_lower_case = true;
90
91 for c in component.chars() {
92 if prev_is_lower_case && c.is_uppercase() {
95 new_word = true;
96 }
97
98 if new_word {
99 camel_cased_component.extend(c.to_uppercase());
100 } else {
101 camel_cased_component.extend(c.to_lowercase());
102 }
103
104 prev_is_lower_case = c.is_lowercase();
105 new_word = false;
106 }
107
108 camel_cased_component
109 })
110 .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
111 let join = if let Some(prev) = prev {
114 let l = prev.chars().last().unwrap();
115 let f = next.chars().next().unwrap();
116 !char_has_case(l) && !char_has_case(f)
117 } else {
118 false
119 };
120 (acc + if join { "_" } else { "" } + &next, Some(next))
121 })
122 .0
123}
124
125impl NonCamelCaseTypes {
126 fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
127 let name = ident.name.as_str();
128
129 if !is_camel_case(name) {
130 let cc = to_camel_case(name);
131 let sub = if *name != cc {
132 NonCamelCaseTypeSub::Suggestion { span: ident.span, replace: cc }
133 } else {
134 NonCamelCaseTypeSub::Label { span: ident.span }
135 };
136 cx.emit_span_lint(
137 NON_CAMEL_CASE_TYPES,
138 ident.span,
139 NonCamelCaseType { sort, name, sub },
140 );
141 }
142 }
143}
144
145impl EarlyLintPass for NonCamelCaseTypes {
146 fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
147 let has_repr_c = #[allow(non_exhaustive_omitted_patterns)] match AttributeParser::parse_limited(cx.sess(),
&it.attrs, sym::repr, it.span, it.id, None) {
Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if
reprs.iter().any(|(r, _)| r == &ReprAttr::ReprC) => true,
_ => false,
}matches!(
148 AttributeParser::parse_limited(cx.sess(), &it.attrs, sym::repr, it.span, it.id, None),
149 Some(Attribute::Parsed(AttributeKind::Repr { reprs, ..})) if reprs.iter().any(|(r, _)| r == &ReprAttr::ReprC)
150 );
151
152 if has_repr_c {
153 return;
154 }
155
156 match &it.kind {
157 ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. })
158 | ast::ItemKind::Enum(ident, ..)
159 | ast::ItemKind::Struct(ident, ..)
160 | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident),
161 ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
162 self.check_case(cx, "trait", ident)
163 }
164 ast::ItemKind::TraitAlias(box ast::TraitAlias { ident, .. }) => {
165 self.check_case(cx, "trait alias", ident)
166 }
167
168 ast::ItemKind::Impl(ast::Impl { of_trait: None, items, .. }) => {
171 for it in items {
172 if let ast::AssocItemKind::Type(alias) = &it.kind {
174 self.check_case(cx, "associated type", &alias.ident);
175 }
176 }
177 }
178 _ => (),
179 }
180 }
181
182 fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
183 if let ast::AssocItemKind::Type(alias) = &it.kind {
184 self.check_case(cx, "associated type", &alias.ident);
185 }
186 }
187
188 fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
189 self.check_case(cx, "variant", &v.ident);
190 }
191
192 fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
193 if let ast::GenericParamKind::Type { .. } = param.kind {
194 self.check_case(cx, "type parameter", ¶m.ident);
195 }
196 }
197}
198
199#[doc = r" The `non_snake_case` lint detects variables, methods, functions,"]
#[doc = r" lifetime parameters and modules that don't have snake case names."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" let MY_VALUE = 5;"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r#" The preferred style for these identifiers is to use "snake case","#]
#[doc =
r" where all the characters are in lowercase, with words separated with a"]
#[doc = r" single underscore, such as `my_value`."]
pub static NON_SNAKE_CASE: &::rustc_lint_defs::Lint =
&::rustc_lint_defs::Lint {
name: "NON_SNAKE_CASE",
default_level: ::rustc_lint_defs::Warn,
desc: "variables, methods, functions, lifetime parameters and modules should have snake case names",
is_externally_loaded: false,
..::rustc_lint_defs::Lint::default_fields_for_macro()
};declare_lint! {
200 pub NON_SNAKE_CASE,
217 Warn,
218 "variables, methods, functions, lifetime parameters and modules should have snake case names"
219}
220
221pub struct NonSnakeCase;
#[automatically_derived]
impl ::core::marker::Copy for NonSnakeCase { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for NonSnakeCase { }
#[automatically_derived]
impl ::core::clone::Clone for NonSnakeCase {
#[inline]
fn clone(&self) -> NonSnakeCase { *self }
}
impl ::rustc_lint_defs::LintPass for NonSnakeCase {
fn name(&self) -> &'static str { "NonSnakeCase" }
fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[NON_SNAKE_CASE]))
}
}
impl NonSnakeCase {
#[allow(unused)]
pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[NON_SNAKE_CASE]))
}
}declare_lint_pass!(NonSnakeCase => [NON_SNAKE_CASE]);
222
223impl NonSnakeCase {
224 fn to_snake_case(mut name: &str) -> String {
225 let mut words = ::alloc::vec::Vec::new()vec![];
226 name = name.trim_start_matches(|c: char| {
228 if c == '_' {
229 words.push(String::new());
230 true
231 } else {
232 false
233 }
234 });
235 for s in name.split('_') {
236 let mut last_upper = false;
237 let mut buf = String::new();
238 if s.is_empty() {
239 continue;
240 }
241 for ch in s.chars() {
242 if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
243 words.push(buf);
244 buf = String::new();
245 }
246 last_upper = ch.is_uppercase();
247 buf.extend(ch.to_lowercase());
248 }
249 words.push(buf);
250 }
251 words.join("_")
252 }
253
254 fn check_snake_case(&self, cx: &LateContext<'_>, sort: &str, ident: &Ident) {
256 fn is_snake_case(ident: &str) -> bool {
257 if ident.is_empty() {
258 return true;
259 }
260 let ident = ident.trim_start_matches('\'');
261 let ident = ident.trim_matches('_');
262
263 if ident.contains("__") {
264 return false;
265 }
266
267 !ident.chars().any(char::is_uppercase)
270 }
271
272 let name = ident.name.as_str();
273
274 if !is_snake_case(name) {
275 let span = ident.span;
276 let sc = NonSnakeCase::to_snake_case(name);
277 let sub = if name != sc {
280 if !span.is_dummy() {
283 let sc_ident = Ident::from_str_and_span(&sc, span);
284 if sc_ident.is_reserved() {
285 if sc_ident.name.can_be_raw() {
289 NonSnakeCaseDiagSub::RenameOrConvertSuggestion {
290 span,
291 suggestion: sc_ident,
292 }
293 } else {
294 NonSnakeCaseDiagSub::SuggestionAndNote { span }
295 }
296 } else {
297 NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion: sc.clone() }
298 }
299 } else {
300 NonSnakeCaseDiagSub::Help
301 }
302 } else {
303 NonSnakeCaseDiagSub::Label { span }
304 };
305 cx.emit_span_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sc, sub });
306 }
307 }
308}
309
310impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
311 fn check_mod(&mut self, cx: &LateContext<'_>, _: &'tcx hir::Mod<'tcx>, id: hir::HirId) {
312 if id != hir::CRATE_HIR_ID {
313 return;
314 }
315
316 if cx.tcx.crate_types().iter().all(|&crate_type| crate_type == CrateType::Executable) {
320 return;
321 }
322
323 let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
324 Some(Ident::from_str(name))
325 } else {
326 {
'done:
{
for i in cx.tcx.hir_krate_attrs() {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(CrateName { name, name_span, ..
}) => {
break 'done Some((name, name_span));
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}find_attr!(cx.tcx, crate, CrateName{name, name_span,..} => (name, name_span)).map(
327 |(&name, &span)| {
328 let sp = cx
330 .sess()
331 .source_map()
332 .span_to_snippet(span)
333 .ok()
334 .and_then(|snippet| {
335 let left = snippet.find('"')?;
336 let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
337
338 Some(
339 span.with_lo(span.lo() + BytePos(left as u32 + 1))
340 .with_hi(span.hi() - BytePos(right as u32)),
341 )
342 })
343 .unwrap_or(span);
344
345 Ident::new(name, sp)
346 },
347 )
348 };
349
350 if let Some(ident) = &crate_ident {
351 self.check_snake_case(cx, "crate", ident);
352 }
353 }
354
355 fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
356 if let GenericParamKind::Lifetime { .. } = param.kind {
357 self.check_snake_case(cx, "lifetime", ¶m.name.ident());
358 }
359 }
360
361 fn check_fn(
362 &mut self,
363 cx: &LateContext<'_>,
364 fk: FnKind<'_>,
365 _: &hir::FnDecl<'_>,
366 _: &hir::Body<'_>,
367 _: Span,
368 id: LocalDefId,
369 ) {
370 match &fk {
371 FnKind::Method(ident, sig, ..) => match cx.tcx.associated_item(id).container {
372 AssocContainer::InherentImpl => {
373 if sig.header.abi != ExternAbi::Rust && {
#[allow(deprecated)]
{
{
'done:
{
for i in cx.tcx.get_all_attrs(id) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NoMangle(..)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}
}.is_some()find_attr!(cx.tcx, id, NoMangle(..)) {
374 return;
375 }
376 self.check_snake_case(cx, "method", ident);
377 }
378 AssocContainer::Trait => {
379 self.check_snake_case(cx, "trait method", ident);
380 }
381 AssocContainer::TraitImpl(_) => {}
382 },
383 FnKind::ItemFn(ident, _, header) => {
384 if header.abi != ExternAbi::Rust && {
#[allow(deprecated)]
{
{
'done:
{
for i in cx.tcx.get_all_attrs(id) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NoMangle(..)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}
}.is_some()find_attr!(cx.tcx, id, NoMangle(..)) {
386 return;
387 }
388 self.check_snake_case(cx, "function", ident);
389 }
390 FnKind::Closure => (),
391 }
392 }
393
394 fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
395 if let hir::ItemKind::Mod(ident, _) = it.kind {
396 self.check_snake_case(cx, "module", &ident);
397 }
398 }
399
400 fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_, hir::AmbigArg>) {
401 if let hir::TyKind::FnPtr(hir::FnPtrTy { param_idents, .. }) = &ty.kind {
402 for param_ident in *param_idents {
403 if let Some(param_ident) = param_ident {
404 self.check_snake_case(cx, "variable", param_ident);
405 }
406 }
407 }
408 }
409
410 fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &hir::TraitItem<'_>) {
411 if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(param_idents)) = item.kind {
412 self.check_snake_case(cx, "trait method", &item.ident);
413 for param_ident in param_idents {
414 if let Some(param_ident) = param_ident {
415 self.check_snake_case(cx, "variable", param_ident);
416 }
417 }
418 }
419 }
420
421 fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
422 if let PatKind::Binding(_, hid, ident, _) = p.kind {
423 if let hir::Node::PatField(field) = cx.tcx.parent_hir_node(hid) {
424 if !field.is_shorthand {
425 self.check_snake_case(cx, "variable", &ident);
428 }
429 return;
430 }
431 self.check_snake_case(cx, "variable", &ident);
432 }
433 }
434
435 fn check_struct_def(&mut self, cx: &LateContext<'_>, s: &hir::VariantData<'_>) {
436 for sf in s.fields() {
437 self.check_snake_case(cx, "structure field", &sf.ident);
438 }
439 }
440}
441
442#[doc =
r" The `non_upper_case_globals` lint detects static items that don't have"]
#[doc = r" uppercase identifiers."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" static max_points: i32 = 5;"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc = r" The preferred style is for static item names to use all uppercase"]
#[doc = r" letters such as `MAX_POINTS`."]
pub static NON_UPPER_CASE_GLOBALS: &::rustc_lint_defs::Lint =
&::rustc_lint_defs::Lint {
name: "NON_UPPER_CASE_GLOBALS",
default_level: ::rustc_lint_defs::Warn,
desc: "static constants should have uppercase identifiers",
is_externally_loaded: false,
..::rustc_lint_defs::Lint::default_fields_for_macro()
};declare_lint! {
443 pub NON_UPPER_CASE_GLOBALS,
459 Warn,
460 "static constants should have uppercase identifiers"
461}
462
463pub struct NonUpperCaseGlobals;
#[automatically_derived]
impl ::core::marker::Copy for NonUpperCaseGlobals { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for NonUpperCaseGlobals { }
#[automatically_derived]
impl ::core::clone::Clone for NonUpperCaseGlobals {
#[inline]
fn clone(&self) -> NonUpperCaseGlobals { *self }
}
impl ::rustc_lint_defs::LintPass for NonUpperCaseGlobals {
fn name(&self) -> &'static str { "NonUpperCaseGlobals" }
fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[NON_UPPER_CASE_GLOBALS]))
}
}
impl NonUpperCaseGlobals {
#[allow(unused)]
pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[NON_UPPER_CASE_GLOBALS]))
}
}declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
464
465struct NonUpperCaseGlobalGenerator<'a, F: FnOnce() -> NonUpperCaseGlobal<'a>> {
466 callback: F,
467}
468
469impl<'a, 'b, F: FnOnce() -> NonUpperCaseGlobal<'b>> Diagnostic<'a, ()>
470 for NonUpperCaseGlobalGenerator<'b, F>
471{
472 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
473 let Self { callback } = self;
474 callback().into_diag(dcx, level)
475 }
476}
477
478impl NonUpperCaseGlobals {
479 fn check_upper_case(cx: &LateContext<'_>, sort: &str, did: Option<LocalDefId>, ident: &Ident) {
480 let name = ident.name.as_str();
481 if name.chars().any(|c| c.is_lowercase()) {
482 let uc = NonSnakeCase::to_snake_case(name).to_uppercase();
483
484 let can_change_usages = if let Some(did) = did {
487 !cx.tcx.effective_visibilities(()).is_exported(did)
488 } else {
489 false
490 };
491
492 let sub = if *name != uc {
495 NonUpperCaseGlobalSub::Suggestion {
496 span: ident.span,
497 replace: uc.clone(),
498 applicability: if can_change_usages {
499 Applicability::MachineApplicable
500 } else {
501 Applicability::MaybeIncorrect
502 },
503 }
504 } else {
505 NonUpperCaseGlobalSub::Label { span: ident.span }
506 };
507
508 struct UsageCollector<'a, 'tcx> {
509 cx: &'tcx LateContext<'a>,
510 did: DefId,
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 if let Some(final_seg) = path.segments.last()
527 && final_seg.res.opt_def_id() == Some(self.did)
528 {
529 self.collected.push(final_seg.ident.span);
530 }
531 }
532 }
533
534 let callback = || {
535 let usages = if can_change_usages
538 && *name != uc
539 && let Some(did) = did
540 {
541 let mut usage_collector =
542 UsageCollector { cx, did: did.to_def_id(), collected: Vec::new() };
543 cx.tcx.hir_walk_toplevel_module(&mut usage_collector);
544 usage_collector
545 .collected
546 .into_iter()
547 .map(|span| NonUpperCaseGlobalSubTool { span, replace: uc.clone() })
548 .collect()
549 } else {
550 ::alloc::vec::Vec::new()vec![]
551 };
552
553 NonUpperCaseGlobal { sort, name, sub, usages }
554 };
555 cx.emit_span_lint(
556 NON_UPPER_CASE_GLOBALS,
557 ident.span,
558 NonUpperCaseGlobalGenerator { callback },
559 );
560 }
561 }
562}
563
564impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
565 fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
566 let attrs = cx.tcx.hir_attrs(it.hir_id());
567 match it.kind {
568 hir::ItemKind::Static(_, ident, ..) if !{
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NoMangle(..)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, NoMangle(..)) => {
569 NonUpperCaseGlobals::check_upper_case(
570 cx,
571 "static variable",
572 Some(it.owner_id.def_id),
573 &ident,
574 );
575 }
576 hir::ItemKind::Const(ident, ..) => {
577 NonUpperCaseGlobals::check_upper_case(
578 cx,
579 "constant",
580 Some(it.owner_id.def_id),
581 &ident,
582 );
583 }
584 _ => {}
585 }
586 }
587
588 fn check_trait_item(&mut self, cx: &LateContext<'_>, ti: &hir::TraitItem<'_>) {
589 if let hir::TraitItemKind::Const(..) = ti.kind {
590 NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ti.ident);
591 }
592 }
593
594 fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
595 if let hir::ImplItemKind::Const(..) = ii.kind
596 && let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind
597 {
598 NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident);
599 }
600 }
601
602 fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
603 if let PatKind::Expr(hir::PatExpr {
605 kind: PatExprKind::Path(hir::QPath::Resolved(None, path)),
606 ..
607 }) = p.kind
608 {
609 if let Res::Def(DefKind::Const { .. }, _) = path.res
610 && let [segment] = path.segments
611 {
612 NonUpperCaseGlobals::check_upper_case(
613 cx,
614 "constant in pattern",
615 None,
616 &segment.ident,
617 );
618 }
619 }
620 }
621
622 fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
623 if let GenericParamKind::Const { .. } = param.kind {
624 NonUpperCaseGlobals::check_upper_case(
625 cx,
626 "const parameter",
627 Some(param.def_id),
628 ¶m.name.ident(),
629 );
630 }
631 }
632}
633
634#[cfg(test)]
635mod tests;