about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbinarycat <binarycat@envs.net>2025-08-05 15:23:14 -0500
committerbinarycat <binarycat@envs.net>2025-08-05 15:34:51 -0500
commit34b358d52aa6842e512dacbf97c7d3a9e18795e6 (patch)
treeb6566fb1c46f8a7c572e22caf4fa57e74a8e8d83
parent213d946a384b46989f6fd9c8ae9c547b4e354455 (diff)
downloadrust-34b358d52aa6842e512dacbf97c7d3a9e18795e6.tar.gz
rust-34b358d52aa6842e512dacbf97c7d3a9e18795e6.zip
rustdoc: fix caching of intra-doc links on reexports
-rw-r--r--src/librustdoc/clean/types.rs20
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs7
-rw-r--r--tests/rustdoc/intra-doc/macro-caching-144965.rs35
3 files changed, 60 insertions, 2 deletions
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 782311e593b..26b087feb16 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -480,10 +480,28 @@ impl Item {
         }
     }
 
+    /// If the item has doc comments from a reexport, returns the item id of that reexport,
+    /// otherwise returns returns the item id.
+    ///
+    /// This is used as a key for caching intra-doc link resolution,
+    /// to prevent two reexports of the same item from using the same cache.
+    pub(crate) fn item_or_reexport_id(&self) -> ItemId {
+        // added documentation on a reexport is always prepended.
+        self.attrs
+            .doc_strings
+            .first()
+            .map(|x| x.item_id)
+            .flatten()
+            .map(ItemId::from)
+            .unwrap_or(self.item_id)
+    }
+
     pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
         use crate::html::format::{href, link_tooltip};
 
-        let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
+        let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else {
+            return vec![];
+        };
         links
             .iter()
             .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index c9fa3a4837f..bcb676cd1f1 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1082,7 +1082,12 @@ impl LinkCollector<'_, '_> {
             for md_link in preprocessed_markdown_links(&doc) {
                 let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
                 if let Some(link) = link {
-                    self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
+                    self.cx
+                        .cache
+                        .intra_doc_links
+                        .entry(item.item_or_reexport_id())
+                        .or_default()
+                        .insert(link);
                 }
             }
         }
diff --git a/tests/rustdoc/intra-doc/macro-caching-144965.rs b/tests/rustdoc/intra-doc/macro-caching-144965.rs
new file mode 100644
index 00000000000..e14b465aeea
--- /dev/null
+++ b/tests/rustdoc/intra-doc/macro-caching-144965.rs
@@ -0,0 +1,35 @@
+// regression test for https://github.com/rust-lang/rust/issues/144965
+
+#![crate_name = "foo"]
+#![no_std]
+
+#[doc(hidden)]
+pub struct MyStruct;
+
+macro_rules! my_macro {
+    () => {
+        pub fn my_function() {}
+
+        /// Incorrect: [`my_function()`].
+        #[doc(inline)]
+        pub use $crate::MyStruct;
+
+        /// Correct: [`my_function`].
+        pub struct AnotherStruct;
+    };
+}
+
+
+pub mod one {
+    //@ has 'foo/one/index.html'
+    //@ has - '//dl[@class="item-table"]/dd[1]/a[@href="fn.my_function.html"]/code' 'my_function'
+    //@ has - '//dl[@class="item-table"]/dd[2]/a[@href="fn.my_function.html"]/code' 'my_function()'
+    my_macro!();
+}
+
+pub mod two {
+    //@ has 'foo/two/index.html'
+    //@ has - '//dl[@class="item-table"]/dd[1]/a[@href="fn.my_function.html"]/code' 'my_function'
+    //@ has - '//dl[@class="item-table"]/dd[2]/a[@href="fn.my_function.html"]/code' 'my_function()'
+    my_macro!();
+}