1
1
use rustc_abi:: ExternAbi ;
2
2
use rustc_attr_data_structures:: { AttributeKind , ReprAttr } ;
3
3
use rustc_attr_parsing:: AttributeParser ;
4
+ use rustc_errors:: Applicability ;
4
5
use rustc_hir:: def:: { DefKind , Res } ;
6
+ use rustc_hir:: def_id:: DefId ;
5
7
use rustc_hir:: intravisit:: { FnKind , Visitor } ;
6
8
use rustc_hir:: { AttrArgs , AttrItem , Attribute , GenericParamKind , PatExprKind , PatKind } ;
7
9
use rustc_middle:: hir:: nested_filter:: All ;
@@ -495,17 +497,33 @@ impl NonUpperCaseGlobals {
495
497
if name. chars ( ) . any ( |c| c. is_lowercase ( ) ) {
496
498
let uc = NonSnakeCase :: to_snake_case ( name) . to_uppercase ( ) ;
497
499
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
+
498
508
// We cannot provide meaningful suggestions
499
509
// if the characters are in the category of "Lowercase Letter".
500
510
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
+ }
502
520
} else {
503
521
NonUpperCaseGlobalSub :: Label { span : ident. span }
504
522
} ;
505
523
506
524
struct UsageCollector < ' a , ' tcx > {
507
525
cx : & ' tcx LateContext < ' a > ,
508
- did : LocalDefId ,
526
+ did : DefId ,
509
527
collected : Vec < Span > ,
510
528
}
511
529
@@ -521,21 +539,23 @@ impl NonUpperCaseGlobals {
521
539
path : & rustc_hir:: Path < ' v > ,
522
540
_id : rustc_hir:: HirId ,
523
541
) -> 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 ) ;
528
546
}
529
547
}
530
548
}
531
549
532
550
cx. emit_span_lint_lazy ( NON_UPPER_CASE_GLOBALS , ident. span , || {
533
551
// Compute usages lazily as it can expansive and useless when the lint is allowed.
534
552
// 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
536
554
&& * name != uc
555
+ && let Some ( did) = did
537
556
{
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 ( ) } ;
539
559
cx. tcx . hir_walk_toplevel_module ( & mut usage_collector) ;
540
560
usage_collector
541
561
. collected
0 commit comments