@@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers;
9
9
use rustc_middle:: ty:: TyCtxt ;
10
10
11
11
use rustc_ast:: { ast, AttrStyle , Attribute , Lit , LitKind , NestedMetaItem } ;
12
- use rustc_data_structures:: stable_set :: FxHashSet ;
12
+ use rustc_data_structures:: fx :: { FxHashMap , FxHashSet } ;
13
13
use rustc_errors:: { pluralize, struct_span_err, Applicability } ;
14
14
use rustc_feature:: { AttributeType , BUILTIN_ATTRIBUTE_MAP } ;
15
15
use rustc_hir as hir;
@@ -66,6 +66,7 @@ impl CheckAttrVisitor<'tcx> {
66
66
target : Target ,
67
67
item : Option < ItemLike < ' _ > > ,
68
68
) {
69
+ let mut doc_aliases = FxHashMap :: default ( ) ;
69
70
let mut is_valid = true ;
70
71
let mut specified_inline = None ;
71
72
let mut seen = FxHashSet :: default ( ) ;
@@ -79,7 +80,13 @@ impl CheckAttrVisitor<'tcx> {
79
80
sym:: track_caller => {
80
81
self . check_track_caller ( hir_id, & attr. span , attrs, span, target)
81
82
}
82
- sym:: doc => self . check_doc_attrs ( attr, hir_id, target, & mut specified_inline) ,
83
+ sym:: doc => self . check_doc_attrs (
84
+ attr,
85
+ hir_id,
86
+ target,
87
+ & mut specified_inline,
88
+ & mut doc_aliases,
89
+ ) ,
83
90
sym:: no_link => self . check_no_link ( hir_id, & attr, span, target) ,
84
91
sym:: export_name => self . check_export_name ( hir_id, & attr, span, target) ,
85
92
sym:: rustc_layout_scalar_valid_range_start
@@ -512,6 +519,7 @@ impl CheckAttrVisitor<'tcx> {
512
519
hir_id : HirId ,
513
520
target : Target ,
514
521
is_list : bool ,
522
+ aliases : & mut FxHashMap < String , Span > ,
515
523
) -> bool {
516
524
let tcx = self . tcx ;
517
525
let err_fn = move |span : Span , msg : & str | {
@@ -582,17 +590,38 @@ impl CheckAttrVisitor<'tcx> {
582
590
if & * item_name. as_str ( ) == doc_alias {
583
591
return err_fn ( meta. span ( ) , "is the same as the item's name" ) ;
584
592
}
593
+ let span = meta. span ( ) ;
594
+ if let Err ( entry) = aliases. try_insert ( doc_alias. to_owned ( ) , span) {
595
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, span, |lint| {
596
+ lint. build ( "doc alias is duplicated" )
597
+ . span_label ( * entry. entry . get ( ) , "first defined here" )
598
+ . emit ( ) ;
599
+ } ) ;
600
+ }
585
601
true
586
602
}
587
603
588
- fn check_doc_alias ( & self , meta : & NestedMetaItem , hir_id : HirId , target : Target ) -> bool {
604
+ fn check_doc_alias (
605
+ & self ,
606
+ meta : & NestedMetaItem ,
607
+ hir_id : HirId ,
608
+ target : Target ,
609
+ aliases : & mut FxHashMap < String , Span > ,
610
+ ) -> bool {
589
611
if let Some ( values) = meta. meta_item_list ( ) {
590
612
let mut errors = 0 ;
591
613
for v in values {
592
614
match v. literal ( ) {
593
615
Some ( l) => match l. kind {
594
616
LitKind :: Str ( s, _) => {
595
- if !self . check_doc_alias_value ( v, & s. as_str ( ) , hir_id, target, true ) {
617
+ if !self . check_doc_alias_value (
618
+ v,
619
+ & s. as_str ( ) ,
620
+ hir_id,
621
+ target,
622
+ true ,
623
+ aliases,
624
+ ) {
596
625
errors += 1 ;
597
626
}
598
627
}
@@ -621,7 +650,7 @@ impl CheckAttrVisitor<'tcx> {
621
650
}
622
651
errors == 0
623
652
} else if let Some ( doc_alias) = meta. value_str ( ) . map ( |s| s. to_string ( ) ) {
624
- self . check_doc_alias_value ( meta, & doc_alias, hir_id, target, false )
653
+ self . check_doc_alias_value ( meta, & doc_alias, hir_id, target, false , aliases )
625
654
} else {
626
655
self . tcx
627
656
. sess
@@ -858,6 +887,7 @@ impl CheckAttrVisitor<'tcx> {
858
887
hir_id : HirId ,
859
888
target : Target ,
860
889
specified_inline : & mut Option < ( bool , Span ) > ,
890
+ aliases : & mut FxHashMap < String , Span > ,
861
891
) -> bool {
862
892
let mut is_valid = true ;
863
893
@@ -867,7 +897,7 @@ impl CheckAttrVisitor<'tcx> {
867
897
match i_meta. name_or_empty ( ) {
868
898
sym:: alias
869
899
if !self . check_attr_not_crate_level ( & meta, hir_id, "alias" )
870
- || !self . check_doc_alias ( & meta, hir_id, target) =>
900
+ || !self . check_doc_alias ( & meta, hir_id, target, aliases ) =>
871
901
{
872
902
is_valid = false
873
903
}
0 commit comments