From e4e2e8bd6f607e16c35c966f16a616daced632e7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Jan 2026 16:37:01 +0100 Subject: [PATCH] Fix `deprecated` attribute intra-doc link not resolved in the right location on reexported item --- .../passes/collect_intra_doc_links.rs | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 07d6efaa97e1..8a37f46b9a96 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -7,7 +7,6 @@ use std::mem; use std::ops::Range; -use rustc_ast::attr::AttributeExt; use rustc_ast::util::comments::may_have_doc_links; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -1038,10 +1037,11 @@ fn preprocessed_markdown_links(s: &str) -> Vec { impl LinkCollector<'_, '_> { #[instrument(level = "debug", skip_all)] fn resolve_links(&mut self, item: &Item) { + let tcx = self.cx.tcx; if !self.cx.document_private() && let Some(def_id) = item.item_id.as_def_id() && let Some(def_id) = def_id.as_local() - && !self.cx.tcx.effective_visibilities(()).is_exported(def_id) + && !tcx.effective_visibilities(()).is_exported(def_id) && !has_primitive_or_keyword_or_attribute_docs(&item.attrs.other_attrs) { // Skip link resolution for non-exported items. @@ -1049,9 +1049,9 @@ fn resolve_links(&mut self, item: &Item) { } let mut insert_links = |item_id, doc: &str| { - let module_id = match self.cx.tcx.def_kind(item_id) { - DefKind::Mod if item.inner_docs(self.cx.tcx) => item_id, - _ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(), + let module_id = match tcx.def_kind(item_id) { + DefKind::Mod if item.inner_docs(tcx) => item_id, + _ => find_nearest_parent_module(tcx, item_id).unwrap(), }; for md_link in preprocessed_markdown_links(&doc) { let link = self.resolve_link(&doc, item, item_id, module_id, &md_link); @@ -1084,7 +1084,14 @@ fn resolve_links(&mut self, item: &Item) { // Also resolve links in the note text of `#[deprecated]`. for attr in &item.attrs.other_attrs { - let Some(note_sym) = attr.deprecation_note() else { continue }; + let rustc_hir::Attribute::Parsed(rustc_hir::attrs::AttributeKind::Deprecation { + span, + deprecation, + }) = attr + else { + continue; + }; + let Some(note_sym) = deprecation.note else { continue }; let note = note_sym.as_str(); if !may_have_doc_links(note) { @@ -1092,7 +1099,18 @@ fn resolve_links(&mut self, item: &Item) { } debug!("deprecated_note={note}"); - insert_links(item.item_id.expect_def_id(), note) + // When resolving an intra-doc link inside a deprecation note that is on an inlined + // `use` statement, we need to use the `def_id` of the `use` statement, not the + // inlined item. + // + let item_id = if let Some(inline_stmt_id) = item.inline_stmt_id + && item.span(tcx).is_none_or(|item_span| !item_span.inner().contains(*span)) + { + inline_stmt_id.to_def_id() + } else { + item.item_id.expect_def_id() + }; + insert_links(item_id, note) } }