11use rustc_abi:: ExternAbi ;
22use rustc_attr_data_structures:: { AttributeKind , ReprAttr } ;
33use rustc_attr_parsing:: AttributeParser ;
4+ use rustc_errors:: Applicability ;
45use rustc_hir:: def:: { DefKind , Res } ;
6+ use rustc_hir:: def_id:: DefId ;
57use rustc_hir:: intravisit:: { FnKind , Visitor } ;
68use rustc_hir:: { AttrArgs , AttrItem , Attribute , GenericParamKind , PatExprKind , PatKind } ;
79use rustc_middle:: hir:: nested_filter:: All ;
@@ -495,17 +497,33 @@ impl NonUpperCaseGlobals {
495497 if name. chars ( ) . any ( |c| c. is_lowercase ( ) ) {
496498 let uc = NonSnakeCase :: to_snake_case ( name) . to_uppercase ( ) ;
497499
500+ // If the item is exported, suggesting changing it's name would be breaking-change
501+ // and could break users without a "nice" applicable fix, so let's avoid it.
502+ let can_change_usages = if let Some ( did) = did {
503+ !cx. tcx . effective_visibilities ( ( ) ) . is_exported ( did)
504+ } else {
505+ false
506+ } ;
507+
498508 // We cannot provide meaningful suggestions
499509 // if the characters are in the category of "Lowercase Letter".
500510 let sub = if * name != uc {
501- NonUpperCaseGlobalSub :: Suggestion { span : ident. span , replace : uc. clone ( ) }
511+ NonUpperCaseGlobalSub :: Suggestion {
512+ span : ident. span ,
513+ replace : uc. clone ( ) ,
514+ applicability : if can_change_usages {
515+ Applicability :: MachineApplicable
516+ } else {
517+ Applicability :: MaybeIncorrect
518+ } ,
519+ }
502520 } else {
503521 NonUpperCaseGlobalSub :: Label { span : ident. span }
504522 } ;
505523
506524 struct UsageCollector < ' a , ' tcx > {
507525 cx : & ' tcx LateContext < ' a > ,
508- did : LocalDefId ,
526+ did : DefId ,
509527 collected : Vec < Span > ,
510528 }
511529
@@ -521,21 +539,23 @@ impl NonUpperCaseGlobals {
521539 path : & rustc_hir:: Path < ' v > ,
522540 _id : rustc_hir:: HirId ,
523541 ) -> Self :: Result {
524- for seg in path. segments {
525- if seg . res . opt_def_id ( ) == Some ( self . did . to_def_id ( ) ) {
526- self . collected . push ( seg . ident . span ) ;
527- }
542+ if let Some ( final_seg ) = path. segments . last ( )
543+ && final_seg . res . opt_def_id ( ) == Some ( self . did )
544+ {
545+ self . collected . push ( final_seg . ident . span ) ;
528546 }
529547 }
530548 }
531549
532550 cx. emit_span_lint_lazy ( NON_UPPER_CASE_GLOBALS , ident. span , || {
533551 // Compute usages lazily as it can expansive and useless when the lint is allowed.
534552 // cf. https://github.com/rust-lang/rust/pull/142645#issuecomment-2993024625
535- let usages = if let Some ( did ) = did
553+ let usages = if can_change_usages
536554 && * name != uc
555+ && let Some ( did) = did
537556 {
538- let mut usage_collector = UsageCollector { cx, did, collected : Vec :: new ( ) } ;
557+ let mut usage_collector =
558+ UsageCollector { cx, did : did. to_def_id ( ) , collected : Vec :: new ( ) } ;
539559 cx. tcx . hir_walk_toplevel_module ( & mut usage_collector) ;
540560 usage_collector
541561 . collected
0 commit comments