about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoshua Nelson <jnelson@cloudflare.com>2022-02-06 18:39:42 -0600
committerJoshua Nelson <jnelson@cloudflare.com>2022-02-06 19:29:31 -0600
commitf026550113b62b7bbd33faf39a7048f5a34fe289 (patch)
tree10418785cdd036c26338d4fdd9fffe8e5a210850
parent7b43cfc9b25ac4a906bd56d32d3111085dd9e6a1 (diff)
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`.
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs24
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules.rs9
2 files changed, 14 insertions, 19 deletions
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 86662ebaaca..8621fe6ba1b 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<Res, ResolutionFailure<'a>> {
-        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 00000000000..a14e4bdf1d7
--- /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() {}