about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2022-01-28 12:12:17 -0700
committerMichael Howell <michael@notriddle.com>2022-01-28 12:24:13 -0700
commit3903ca197e55f209b2415e566b4b8f407f6fe899 (patch)
tree943b210e4fefdd8e39651121e881deb492a9a67e
parent427eba2f0bacdeaebc992a78eb2889564de7d7cf (diff)
downloadrust-3903ca197e55f209b2415e566b4b8f407f6fe899.tar.gz
rust-3903ca197e55f209b2415e566b4b8f407f6fe899.zip
rustdoc: load the set of in-scope traits for modules with no docstring
Fixes #93428

This fix is a response to a couple of special cases related to the
`module_id`, which is eventually used for trait candidates:

  * The module id is always set to the current crate, when checking `crate::`.

    Normally, the set of in-scope traits would be set in `load_links_in_attrs`,
    but if there are no doc comments, then that loop will never run.

  * the module id is set to the parent module, when resolving a module
    that is spelled like this:

        // Notice how we use an outlined doc comment here!
        // [`Test::my_fn`]
        mod something {
        }

    As with the above problem with `crate::`, we need to make sure the
    module gets its traits in scope resolved, even if it has no doc comments
    of its own.
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs10
-rw-r--r--src/test/rustdoc/intra-doc/crate-relative.rs13
-rw-r--r--src/test/rustdoc/intra-doc/mod-relative.rs17
4 files changed, 41 insertions, 0 deletions
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index e1747f3e392..86662ebaaca 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -920,6 +920,7 @@ fn trait_assoc_to_impl_assoc_item<'tcx>(
 ///
 /// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
 /// So it is not stable to serialize cross-crate.
+#[instrument(level = "debug", skip(cx))]
 fn trait_impls_for<'a>(
     cx: &mut DocContext<'a>,
     ty: Ty<'a>,
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index 34aae4b6e39..edd4e9da66d 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -32,6 +32,11 @@ crate fn early_resolve_intra_doc_links(
         all_trait_impls: Default::default(),
     };
 
+    // Because of the `crate::` prefix, any doc comment can reference
+    // the crate root's set of in-scope traits. This line makes sure
+    // it's available.
+    loader.add_traits_in_scope(CRATE_DEF_ID.to_def_id());
+
     // Overridden `visit_item` below doesn't apply to the crate root,
     // so we have to visit its attributes and reexports separately.
     loader.load_links_in_attrs(&krate.attrs, krate.span);
@@ -180,6 +185,11 @@ impl Visitor<'_> for IntraLinkCrateLoader<'_, '_> {
         if let ItemKind::Mod(..) = item.kind {
             let old_mod = mem::replace(&mut self.current_mod, self.resolver.local_def_id(item.id));
 
+            // A module written with a outline doc comments will resolve traits relative
+            // to the parent module. Make sure the parent module's traits-in-scope are
+            // loaded, even if the module itself has no doc comments.
+            self.add_traits_in_parent_scope(self.current_mod.to_def_id());
+
             self.load_links_in_attrs(&item.attrs, item.span);
             self.process_module_children_or_reexports(self.current_mod.to_def_id());
             visit::walk_item(self, item);
diff --git a/src/test/rustdoc/intra-doc/crate-relative.rs b/src/test/rustdoc/intra-doc/crate-relative.rs
new file mode 100644
index 00000000000..bacbcabfc60
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/crate-relative.rs
@@ -0,0 +1,13 @@
+pub struct Test<'a> {
+    data: &'a (),
+}
+
+impl<'a> Test<'a> {
+    pub fn do_test(&self) {}
+}
+
+// @has crate_relative/demo/index.html
+// @has - '//a/@href' '../struct.Test.html#method.do_test'
+pub mod demo {
+    //! [`crate::Test::do_test`]
+}
diff --git a/src/test/rustdoc/intra-doc/mod-relative.rs b/src/test/rustdoc/intra-doc/mod-relative.rs
new file mode 100644
index 00000000000..49d3399b972
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/mod-relative.rs
@@ -0,0 +1,17 @@
+pub mod wrapper {
+
+    pub struct Test<'a> {
+        data: &'a (),
+    }
+
+    impl<'a> Test<'a> {
+        pub fn do_test(&self) {}
+    }
+
+    // @has mod_relative/wrapper/demo/index.html
+    // @has - '//a/@href' '../struct.Test.html#method.do_test'
+    /// [`Test::do_test`]
+    pub mod demo {
+    }
+
+}