From f026550113b62b7bbd33faf39a7048f5a34fe289 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 6 Feb 2022 18:39:42 -0600 Subject: [PATCH] rustdoc: Special-case macro lookups less Previously, rustdoc had 3 fallbacks it used: 1. `resolve_macro_path` 2. `all_macros` 3. `resolve_str_path_error` Ideally, it would only use `resolve_str_path_error`, to be consistent with other namespaces. Unfortunately, that doesn't consider macros that aren't defined at module scope; consider for instance ```rust { struct S; macro_rules! mac { () => {} } // `mac`'s scope starts here /// `mac` <- `resolve_str_path_error` won't see this struct Z; //`mac`'s scope ends here } ``` This changes it to only use `all_macros` and `resolve_str_path_error`, and gives `resolve_str_path_error` precedence over `all_macros` in case there are two macros with the same name in the same module. This also adds a failing test case which will catch trying to remove `all_macros`. --- .../passes/collect_intra_doc_links.rs | 24 ++++--------------- src/test/rustdoc-ui/intra-doc/macro-rules.rs | 9 +++++++ 2 files changed, 14 insertions(+), 19 deletions(-) create mode 100644 src/test/rustdoc-ui/intra-doc/macro-rules.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 86662ebaaca21..8621fe6ba1b93 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -2,10 +2,8 @@ //! //! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md -use rustc_ast as ast; use rustc_data_structures::{fx::FxHashMap, stable_set::FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_expand::base::SyntaxExtensionKind; use rustc_hir::def::{ DefKind, Namespace::{self, *}, @@ -14,7 +12,6 @@ use rustc_hir::def::{ use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID}; use rustc_middle::ty::{DefIdTree, Ty, TyCtxt}; use rustc_middle::{bug, span_bug, ty}; -use rustc_resolve::ParentScope; use rustc_session::lint::Lint; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -486,23 +483,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { path_str: &'a str, module_id: DefId, ) -> Result> { - let path = ast::Path::from_ident(Ident::from_str(path_str)); self.cx.enter_resolver(|resolver| { - // FIXME(jynelson): does this really need 3 separate lookups? - if let Ok((Some(ext), res)) = resolver.resolve_macro_path( - &path, - None, - &ParentScope::module(resolver.graph_root(), resolver), - false, - false, - ) { - if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind { - return Ok(res.try_into().unwrap()); - } - } - if let Some(&res) = resolver.all_macros().get(&Symbol::intern(path_str)) { - return Ok(res.try_into().unwrap()); - } + // NOTE: this needs 2 separate lookups because `resolve_str_path_error` doesn't take + // lexical scope into account (it ignores all macros not defined at the mod-level) debug!("resolving {} as a macro in the module {:?}", path_str, module_id); if let Ok((_, res)) = resolver.resolve_str_path_error(DUMMY_SP, path_str, MacroNS, module_id) @@ -512,6 +495,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { return Ok(res); } } + if let Some(&res) = resolver.all_macros().get(&Symbol::intern(path_str)) { + return Ok(res.try_into().unwrap()); + } Err(ResolutionFailure::NotResolved { module_id, partial_res: None, diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules.rs b/src/test/rustdoc-ui/intra-doc/macro-rules.rs new file mode 100644 index 0000000000000..a14e4bdf1d706 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/macro-rules.rs @@ -0,0 +1,9 @@ +// check-pass +#![allow(rustdoc::private_intra_doc_links)] + +macro_rules! foo { + () => {}; +} + +/// [foo!] +pub fn baz() {}