@@ -12,6 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1212use rustc_middle:: ty;
1313use rustc_resolve:: ParentScope ;
1414use rustc_session:: lint;
15+ use rustc_span:: hygiene:: MacroKind ;
1516use rustc_span:: symbol:: Ident ;
1617use rustc_span:: symbol:: Symbol ;
1718use rustc_span:: DUMMY_SP ;
@@ -122,6 +123,42 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
122123 }
123124 }
124125
126+ /// Resolves a string as a macro.
127+ fn macro_resolve ( & self , path_str : & str , parent_id : Option < hir:: HirId > ) -> Option < Res > {
128+ let cx = self . cx ;
129+ let path = ast:: Path :: from_ident ( Ident :: from_str ( path_str) ) ;
130+ cx. enter_resolver ( |resolver| {
131+ if let Ok ( ( Some ( ext) , res) ) = resolver. resolve_macro_path (
132+ & path,
133+ None ,
134+ & ParentScope :: module ( resolver. graph_root ( ) ) ,
135+ false ,
136+ false ,
137+ ) {
138+ if let SyntaxExtensionKind :: LegacyBang { .. } = ext. kind {
139+ return Some ( res. map_id ( |_| panic ! ( "unexpected id" ) ) ) ;
140+ }
141+ }
142+ if let Some ( res) = resolver. all_macros ( ) . get ( & Symbol :: intern ( path_str) ) {
143+ return Some ( res. map_id ( |_| panic ! ( "unexpected id" ) ) ) ;
144+ }
145+ if let Some ( module_id) = parent_id. or ( self . mod_ids . last ( ) . cloned ( ) ) {
146+ let module_id = cx. tcx . hir ( ) . local_def_id ( module_id) ;
147+ if let Ok ( ( _, res) ) =
148+ resolver. resolve_str_path_error ( DUMMY_SP , path_str, MacroNS , module_id)
149+ {
150+ // don't resolve builtins like `#[derive]`
151+ if let Res :: Def ( ..) = res {
152+ let res = res. map_id ( |_| panic ! ( "unexpected node_id" ) ) ;
153+ return Some ( res) ;
154+ }
155+ }
156+ } else {
157+ debug ! ( "attempting to resolve item without parent module: {}" , path_str) ;
158+ }
159+ None
160+ } )
161+ }
125162 /// Resolves a string as a path within a particular namespace. Also returns an optional
126163 /// URL fragment in the case of variants and methods.
127164 fn resolve (
@@ -371,6 +408,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
371408 }
372409}
373410
411+ /// Check for resolve collisions between a trait and its derive
412+ ///
413+ /// These are common and we should just resolve to the trait in that case
414+ fn is_derive_trait_collision < T > ( ns : & PerNS < Option < ( Res , T ) > > ) -> bool {
415+ if let PerNS {
416+ type_ns : Some ( ( Res :: Def ( DefKind :: Trait , _) , _) ) ,
417+ macro_ns : Some ( ( Res :: Def ( DefKind :: Macro ( MacroKind :: Derive ) , _) , _) ) ,
418+ ..
419+ } = * ns
420+ {
421+ true
422+ } else {
423+ false
424+ }
425+ }
426+
374427impl < ' a , ' tcx > DocFolder for LinkCollector < ' a , ' tcx > {
375428 fn fold_item ( & mut self , mut item : Item ) -> Option < Item > {
376429 let item_hir_id = if item. is_mod ( ) {
@@ -532,6 +585,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
532585 } else if link. starts_with ( "macro@" ) {
533586 kind = Some ( MacroNS ) ;
534587 link. trim_start_matches ( "macro@" )
588+ } else if link. starts_with ( "derive@" ) {
589+ kind = Some ( MacroNS ) ;
590+ link. trim_start_matches ( "derive@" )
535591 } else if link. ends_with ( '!' ) {
536592 kind = Some ( MacroNS ) ;
537593 link. trim_end_matches ( '!' )
@@ -614,8 +670,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
614670 }
615671 None => {
616672 // Try everything!
617- let candidates = PerNS {
618- macro_ns : macro_resolve ( cx, path_str)
673+ let mut candidates = PerNS {
674+ macro_ns : self
675+ . macro_resolve ( path_str, base_node)
619676 . map ( |res| ( res, extra_fragment. clone ( ) ) ) ,
620677 type_ns : match self . resolve (
621678 path_str,
@@ -668,10 +725,16 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
668725 continue ;
669726 }
670727
671- let is_unambiguous = candidates. clone ( ) . present_items ( ) . count ( ) == 1 ;
672- if is_unambiguous {
728+ let len = candidates. clone ( ) . present_items ( ) . count ( ) ;
729+
730+ if len == 1 {
673731 candidates. present_items ( ) . next ( ) . unwrap ( )
732+ } else if len == 2 && is_derive_trait_collision ( & candidates) {
733+ candidates. type_ns . unwrap ( )
674734 } else {
735+ if is_derive_trait_collision ( & candidates) {
736+ candidates. macro_ns = None ;
737+ }
675738 ambiguity_error (
676739 cx,
677740 & item,
@@ -684,7 +747,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
684747 }
685748 }
686749 Some ( MacroNS ) => {
687- if let Some ( res) = macro_resolve ( cx , path_str ) {
750+ if let Some ( res) = self . macro_resolve ( path_str , base_node ) {
688751 ( res, extra_fragment)
689752 } else {
690753 resolution_failure ( cx, & item, path_str, & dox, link_range) ;
@@ -727,28 +790,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
727790 }
728791}
729792
730- /// Resolves a string as a macro.
731- fn macro_resolve ( cx : & DocContext < ' _ > , path_str : & str ) -> Option < Res > {
732- let path = ast:: Path :: from_ident ( Ident :: from_str ( path_str) ) ;
733- cx. enter_resolver ( |resolver| {
734- if let Ok ( ( Some ( ext) , res) ) = resolver. resolve_macro_path (
735- & path,
736- None ,
737- & ParentScope :: module ( resolver. graph_root ( ) ) ,
738- false ,
739- false ,
740- ) {
741- if let SyntaxExtensionKind :: LegacyBang { .. } = ext. kind {
742- return Some ( res. map_id ( |_| panic ! ( "unexpected id" ) ) ) ;
743- }
744- }
745- if let Some ( res) = resolver. all_macros ( ) . get ( & Symbol :: intern ( path_str) ) {
746- return Some ( res. map_id ( |_| panic ! ( "unexpected id" ) ) ) ;
747- }
748- None
749- } )
750- }
751-
752793fn build_diagnostic (
753794 cx : & DocContext < ' _ > ,
754795 item : & Item ,
@@ -916,7 +957,7 @@ fn ambiguity_error(
916957 Res :: Def ( DefKind :: AssocFn | DefKind :: Fn , _) => {
917958 ( "add parentheses" , format ! ( "{}()" , path_str) )
918959 }
919- Res :: Def ( DefKind :: Macro ( .. ) , _) => {
960+ Res :: Def ( DefKind :: Macro ( MacroKind :: Bang ) , _) => {
920961 ( "add an exclamation mark" , format ! ( "{}!" , path_str) )
921962 }
922963 _ => {
@@ -930,6 +971,9 @@ fn ambiguity_error(
930971 ( Res :: Def ( DefKind :: Mod , _) , _) => "module" ,
931972 ( _, TypeNS ) => "type" ,
932973 ( _, ValueNS ) => "value" ,
974+ ( Res :: Def ( DefKind :: Macro ( MacroKind :: Derive ) , _) , MacroNS ) => {
975+ "derive"
976+ }
933977 ( _, MacroNS ) => "macro" ,
934978 } ;
935979
0 commit comments