@@ -11,6 +11,7 @@ use rustc_ast::{
11
11
Item , ItemKind , MethodCall , NodeId , Path , PathSegment , Ty , TyKind ,
12
12
} ;
13
13
use rustc_ast_pretty:: pprust:: where_bound_predicate_to_string;
14
+ use rustc_attr_parsing:: is_doc_alias_attrs_contain_symbol;
14
15
use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
15
16
use rustc_errors:: codes:: * ;
16
17
use rustc_errors:: {
@@ -39,7 +40,7 @@ use crate::late::{
39
40
} ;
40
41
use crate :: ty:: fast_reject:: SimplifiedType ;
41
42
use crate :: {
42
- Module , ModuleKind , ModuleOrUniformRoot , PathResult , PathSource , Segment , errors,
43
+ Module , ModuleKind , ModuleOrUniformRoot , PathResult , PathSource , Resolver , Segment , errors,
43
44
path_names_to_string,
44
45
} ;
45
46
@@ -477,6 +478,19 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
477
478
return ( err, Vec :: new ( ) ) ;
478
479
}
479
480
481
+ if let Some ( ( did, item) ) = self . lookup_doc_alias_name ( path, source. namespace ( ) ) {
482
+ let item_name = item. name ;
483
+ let suggestion_name = self . r . tcx . item_name ( did) ;
484
+ err. span_suggestion (
485
+ item. span ,
486
+ format ! ( "`{suggestion_name}` has a name defined in the doc alias attribute as `{item_name}`" ) ,
487
+ suggestion_name,
488
+ Applicability :: MaybeIncorrect
489
+ ) ;
490
+
491
+ return ( err, Vec :: new ( ) ) ;
492
+ } ;
493
+
480
494
let ( found, suggested_candidates, mut candidates) = self . try_lookup_name_relaxed (
481
495
& mut err,
482
496
source,
@@ -852,6 +866,57 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
852
866
( false , suggested_candidates, candidates)
853
867
}
854
868
869
+ fn lookup_doc_alias_name ( & mut self , path : & [ Segment ] , ns : Namespace ) -> Option < ( DefId , Ident ) > {
870
+ let find_doc_alias_name = |r : & mut Resolver < ' ra , ' _ > , m : Module < ' ra > , item_name : Symbol | {
871
+ for resolution in r. resolutions ( m) . borrow ( ) . values ( ) {
872
+ let Some ( did) =
873
+ resolution. borrow ( ) . binding . and_then ( |binding| binding. res ( ) . opt_def_id ( ) )
874
+ else {
875
+ continue ;
876
+ } ;
877
+ if did. is_local ( ) {
878
+ // We don't record the doc alias name in the local crate
879
+ // because the people who write doc alias are usually not
880
+ // confused by them.
881
+ continue ;
882
+ }
883
+ if is_doc_alias_attrs_contain_symbol ( r. tcx . get_attrs ( did, sym:: doc) , item_name) {
884
+ return Some ( did) ;
885
+ }
886
+ }
887
+ None
888
+ } ;
889
+
890
+ if path. len ( ) == 1 {
891
+ for rib in self . ribs [ ns] . iter ( ) . rev ( ) {
892
+ let item = path[ 0 ] . ident ;
893
+ if let RibKind :: Module ( module) = rib. kind
894
+ && let Some ( did) = find_doc_alias_name ( self . r , module, item. name )
895
+ {
896
+ return Some ( ( did, item) ) ;
897
+ }
898
+ }
899
+ } else {
900
+ for ( idx, seg) in path. iter ( ) . enumerate ( ) . rev ( ) . skip ( 1 ) {
901
+ let Some ( id) = seg. id else {
902
+ continue ;
903
+ } ;
904
+ let Some ( res) = self . r . partial_res_map . get ( & id) else {
905
+ continue ;
906
+ } ;
907
+ if let Res :: Def ( DefKind :: Mod , module) = res. expect_full_res ( )
908
+ && let Some ( module) = self . r . get_module ( module)
909
+ && let item = path[ idx + 1 ] . ident
910
+ && let Some ( did) = find_doc_alias_name ( self . r , module, item. name )
911
+ {
912
+ return Some ( ( did, item) ) ;
913
+ }
914
+ break ;
915
+ }
916
+ }
917
+ None
918
+ }
919
+
855
920
fn suggest_trait_and_bounds (
856
921
& mut self ,
857
922
err : & mut Diag < ' _ > ,
0 commit comments