22//!
33//! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
44
5+ use pulldown_cmark:: LinkType ;
56use rustc_data_structures:: { fx:: FxHashMap , intern:: Interned , stable_set:: FxHashSet } ;
67use rustc_errors:: { Applicability , Diagnostic } ;
7- use rustc_hir:: def:: {
8- DefKind ,
9- Namespace :: { self , * } ,
10- PerNS ,
11- } ;
8+ use rustc_hir:: def:: Namespace :: * ;
9+ use rustc_hir:: def:: { DefKind , Namespace , PerNS } ;
1210use rustc_hir:: def_id:: { DefId , CRATE_DEF_ID } ;
1311use rustc_hir:: Mutability ;
1412use rustc_middle:: ty:: { DefIdTree , Ty , TyCtxt } ;
@@ -19,10 +17,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
1917use rustc_span:: { BytePos , DUMMY_SP } ;
2018use smallvec:: { smallvec, SmallVec } ;
2119
22- use pulldown_cmark:: LinkType ;
23-
2420use std:: borrow:: Cow ;
25- use std:: convert:: { TryFrom , TryInto } ;
2621use std:: fmt:: Write ;
2722use std:: mem;
2823use std:: ops:: Range ;
@@ -487,25 +482,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
487482 item_id : ItemId ,
488483 module_id : DefId ,
489484 ) -> Result < Res , ResolutionFailure < ' a > > {
490- self . cx . enter_resolver ( |resolver| {
491- // NOTE: this needs 2 separate lookups because `resolve_rustdoc_path` doesn't take
492- // lexical scope into account (it ignores all macros not defined at the mod-level)
493- debug ! ( "resolving {} as a macro in the module {:?}" , path_str, module_id) ;
494- if let Some ( res) = resolver. resolve_rustdoc_path ( path_str, MacroNS , module_id) {
495- // don't resolve builtins like `#[derive]`
496- if let Ok ( res) = res. try_into ( ) {
497- return Ok ( res) ;
498- }
499- }
500- if let Some ( & res) = resolver. all_macros ( ) . get ( & Symbol :: intern ( path_str) ) {
501- return Ok ( res. try_into ( ) . unwrap ( ) ) ;
502- }
503- Err ( ResolutionFailure :: NotResolved {
485+ self . resolve_path ( path_str, MacroNS , item_id, module_id) . ok_or_else ( || {
486+ ResolutionFailure :: NotResolved {
504487 item_id,
505488 module_id,
506489 partial_res : None ,
507490 unresolved : path_str. into ( ) ,
508- } )
491+ }
509492 } )
510493 }
511494
@@ -539,6 +522,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
539522 } )
540523 }
541524
525+ /// HACK: Try to search the macro name in the list of all `macro_rules` items in the crate.
526+ /// Used when nothing else works, may often give an incorrect result.
527+ fn resolve_macro_rules ( & self , path_str : & str , ns : Namespace ) -> Option < Res > {
528+ if ns != MacroNS {
529+ return None ;
530+ }
531+
532+ self . cx
533+ . resolver_caches
534+ . all_macro_rules
535+ . get ( & Symbol :: intern ( path_str) )
536+ . copied ( )
537+ . and_then ( |res| res. try_into ( ) . ok ( ) )
538+ }
539+
542540 /// Convenience wrapper around `resolve_rustdoc_path`.
543541 ///
544542 /// This also handles resolving `true` and `false` as booleans.
@@ -560,7 +558,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
560558 . cx
561559 . enter_resolver ( |resolver| resolver. resolve_rustdoc_path ( path_str, ns, module_id) )
562560 . and_then ( |res| res. try_into ( ) . ok ( ) )
563- . or_else ( || resolve_primitive ( path_str, ns) ) ;
561+ . or_else ( || resolve_primitive ( path_str, ns) )
562+ . or_else ( || self . resolve_macro_rules ( path_str, ns) ) ;
564563 debug ! ( "{} resolved to {:?} in namespace {:?}" , path_str, result, ns) ;
565564 result
566565 }
0 commit comments