From 8437d7b1d30b62b0ada5afd21ba4f9e32635bf31 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Sep 2020 22:32:20 -0400 Subject: [PATCH 1/2] Resolve `crate` properly across crates --- src/librustdoc/passes/collect_intra_doc_links.rs | 13 ++++++++++++- .../auxiliary/intra-link-cross-crate-crate.rs | 5 +++++ src/test/rustdoc/intra-link-cross-crate-crate.rs | 6 ++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/auxiliary/intra-link-cross-crate-crate.rs create mode 100644 src/test/rustdoc/intra-link-cross-crate-crate.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5d74a3da9a205..a463c0a3c9cda 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -911,7 +911,7 @@ impl LinkCollector<'_, '_> { parent_node }; - let module_id = if let Some(id) = base_node { + let mut module_id = if let Some(id) = base_node { id } else { debug!("attempting to resolve item without parent module: {}", path_str); @@ -934,6 +934,17 @@ impl LinkCollector<'_, '_> { resolved_self = format!("{}::{}", name, &path_str[6..]); path_str = &resolved_self; } + } else if path_str.starts_with("crate::") { + use rustc_span::def_id::CRATE_DEF_INDEX; + + // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented. + // But rustdoc wants it to mean the crate this item was originally present in. + // To work around this, remove it and resolve relative to the crate root instead. + // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous + // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root. + resolved_self = format!("self::{}", &path_str["crate::".len()..]); + path_str = &resolved_self; + module_id = DefId { krate: item.def_id.krate, index: CRATE_DEF_INDEX }; } match self.resolve_with_disambiguator( diff --git a/src/test/rustdoc/auxiliary/intra-link-cross-crate-crate.rs b/src/test/rustdoc/auxiliary/intra-link-cross-crate-crate.rs new file mode 100644 index 0000000000000..a37848e23d993 --- /dev/null +++ b/src/test/rustdoc/auxiliary/intra-link-cross-crate-crate.rs @@ -0,0 +1,5 @@ +#![crate_name = "inner"] + +/// Links to [crate::g] +pub fn f() {} +pub fn g() {} diff --git a/src/test/rustdoc/intra-link-cross-crate-crate.rs b/src/test/rustdoc/intra-link-cross-crate-crate.rs new file mode 100644 index 0000000000000..edf544708b628 --- /dev/null +++ b/src/test/rustdoc/intra-link-cross-crate-crate.rs @@ -0,0 +1,6 @@ +// aux-build:intra-link-cross-crate-crate.rs +// build-aux-docs +#![crate_name = "outer"] +extern crate inner; +// @has outer/fn.f.html '//a[@href="../inner/fn.g.html"]' "crate::g" +pub use inner::f; From 406584621a4e2d3752b2444c5bed2218447f0bfe Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Sep 2020 23:44:12 -0400 Subject: [PATCH 2/2] Use relative links instead of intra-doc links Previously, `BTreeMap` tried to link to `crate::collections`, intending for the link to go to `std/collections/index.html`. But `BTreeMap` is defined in `alloc`, so after the fix in the previous commit, the links instead went to `alloc/collections/index.html`, which has almost no information. This changes it to link to `index.html`, which only works when viewing from `std::collections::BTreeMap`, the most common place to visit the docs. Fixing it to work from anywhere would require the docs for `std::collections` to be duplicated in `alloc::collections`, which in turn would require HashMap to be `alloc` for intra-doc links to work (https://github.com/rust-lang/rust/issues/74481). --- library/alloc/src/collections/btree/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index b4e9929af5ff2..3fb03a5412e4f 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -811,7 +811,7 @@ impl BTreeMap { /// types that can be `==` without being identical. See the [module-level /// documentation] for more. /// - /// [module-level documentation]: crate::collections#insert-and-complex-keys + /// [module-level documentation]: index.html#insert-and-complex-keys /// /// # Examples ///