@@ -12,6 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
12
12
use rustc_middle:: ty;
13
13
use rustc_resolve:: ParentScope ;
14
14
use rustc_session:: lint;
15
+ use rustc_span:: hygiene:: MacroKind ;
15
16
use rustc_span:: symbol:: Ident ;
16
17
use rustc_span:: symbol:: Symbol ;
17
18
use rustc_span:: DUMMY_SP ;
@@ -122,6 +123,42 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
122
123
}
123
124
}
124
125
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
+ }
125
162
/// Resolves a string as a path within a particular namespace. Also returns an optional
126
163
/// URL fragment in the case of variants and methods.
127
164
fn resolve (
@@ -371,6 +408,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
371
408
}
372
409
}
373
410
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
+
374
427
impl < ' a , ' tcx > DocFolder for LinkCollector < ' a , ' tcx > {
375
428
fn fold_item ( & mut self , mut item : Item ) -> Option < Item > {
376
429
let item_hir_id = if item. is_mod ( ) {
@@ -532,6 +585,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
532
585
} else if link. starts_with ( "macro@" ) {
533
586
kind = Some ( MacroNS ) ;
534
587
link. trim_start_matches ( "macro@" )
588
+ } else if link. starts_with ( "derive@" ) {
589
+ kind = Some ( MacroNS ) ;
590
+ link. trim_start_matches ( "derive@" )
535
591
} else if link. ends_with ( '!' ) {
536
592
kind = Some ( MacroNS ) ;
537
593
link. trim_end_matches ( '!' )
@@ -614,8 +670,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
614
670
}
615
671
None => {
616
672
// 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)
619
676
. map ( |res| ( res, extra_fragment. clone ( ) ) ) ,
620
677
type_ns : match self . resolve (
621
678
path_str,
@@ -668,10 +725,16 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
668
725
continue ;
669
726
}
670
727
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 {
673
731
candidates. present_items ( ) . next ( ) . unwrap ( )
732
+ } else if len == 2 && is_derive_trait_collision ( & candidates) {
733
+ candidates. type_ns . unwrap ( )
674
734
} else {
735
+ if is_derive_trait_collision ( & candidates) {
736
+ candidates. macro_ns = None ;
737
+ }
675
738
ambiguity_error (
676
739
cx,
677
740
& item,
@@ -684,7 +747,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
684
747
}
685
748
}
686
749
Some ( MacroNS ) => {
687
- if let Some ( res) = macro_resolve ( cx , path_str ) {
750
+ if let Some ( res) = self . macro_resolve ( path_str , base_node ) {
688
751
( res, extra_fragment)
689
752
} else {
690
753
resolution_failure ( cx, & item, path_str, & dox, link_range) ;
@@ -727,28 +790,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
727
790
}
728
791
}
729
792
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
-
752
793
fn build_diagnostic (
753
794
cx : & DocContext < ' _ > ,
754
795
item : & Item ,
@@ -916,7 +957,7 @@ fn ambiguity_error(
916
957
Res :: Def ( DefKind :: AssocFn | DefKind :: Fn , _) => {
917
958
( "add parentheses" , format ! ( "{}()" , path_str) )
918
959
}
919
- Res :: Def ( DefKind :: Macro ( .. ) , _) => {
960
+ Res :: Def ( DefKind :: Macro ( MacroKind :: Bang ) , _) => {
920
961
( "add an exclamation mark" , format ! ( "{}!" , path_str) )
921
962
}
922
963
_ => {
@@ -930,6 +971,9 @@ fn ambiguity_error(
930
971
( Res :: Def ( DefKind :: Mod , _) , _) => "module" ,
931
972
( _, TypeNS ) => "type" ,
932
973
( _, ValueNS ) => "value" ,
974
+ ( Res :: Def ( DefKind :: Macro ( MacroKind :: Derive ) , _) , MacroNS ) => {
975
+ "derive"
976
+ }
933
977
( _, MacroNS ) => "macro" ,
934
978
} ;
935
979
0 commit comments