Rollup merge of #93441 - notriddle:notriddle/collect-crate-doc-links-very-early, r=petrochenkov

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.
This commit is contained in:
Matthias Krüger 2022-01-30 00:04:15 +01:00 committed by GitHub
commit 605ffd6113
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 0 deletions

View File

@ -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>,

View File

@ -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);

View File

@ -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`]
}

View File

@ -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 {
}
}