Skip to content

Commit 10fca81

Browse files
Fix invalid jump to def macro link generation
1 parent 38bc246 commit 10fca81

File tree

2 files changed

+35
-34
lines changed

2 files changed

+35
-34
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,26 @@ pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol>
227227
tcx.def_path(def_id).data.into_iter().filter_map(|elem| elem.data.get_opt_name()).collect()
228228
}
229229

230+
pub(crate) fn get_item_path(tcx: TyCtxt<'_>, def_id: DefId, kind: ItemType) -> Vec<Symbol> {
231+
let crate_name = tcx.crate_name(def_id.krate);
232+
let relative = item_relative_path(tcx, def_id);
233+
234+
if let ItemType::Macro = kind {
235+
// Check to see if it is a macro 2.0 or built-in macro
236+
// More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
237+
if matches!(
238+
CStore::from_tcx(tcx).load_macro_untracked(def_id, tcx),
239+
LoadedMacro::MacroDef { def, .. } if !def.macro_rules
240+
) {
241+
once(crate_name).chain(relative).collect()
242+
} else {
243+
vec![crate_name, *relative.last().expect("relative was empty")]
244+
}
245+
} else {
246+
once(crate_name).chain(relative).collect()
247+
}
248+
}
249+
230250
/// Record an external fully qualified name in the external_paths cache.
231251
///
232252
/// These names are used later on by HTML rendering to generate things like
@@ -240,27 +260,12 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
240260
return;
241261
}
242262

243-
let crate_name = cx.tcx.crate_name(did.krate);
244-
245-
let relative = item_relative_path(cx.tcx, did);
246-
let fqn = if let ItemType::Macro = kind {
247-
// Check to see if it is a macro 2.0 or built-in macro
248-
if matches!(
249-
CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx),
250-
LoadedMacro::MacroDef { def, .. } if !def.macro_rules
251-
) {
252-
once(crate_name).chain(relative).collect()
253-
} else {
254-
vec![crate_name, *relative.last().expect("relative was empty")]
255-
}
256-
} else {
257-
once(crate_name).chain(relative).collect()
258-
};
263+
let item_path = get_item_path(cx.tcx, did, kind);
259264

260265
if did.is_local() {
261-
cx.cache.exact_paths.insert(did, fqn);
266+
cx.cache.exact_paths.insert(did, item_path);
262267
} else {
263-
cx.cache.external_paths.insert(did, (fqn, kind));
268+
cx.cache.external_paths.insert(did, (item_path, kind));
264269
}
265270
}
266271

src/librustdoc/html/format.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use rustc_abi::ExternAbi;
1717
use rustc_ast::join_path_syms;
1818
use rustc_data_structures::fx::FxHashSet;
1919
use rustc_hir as hir;
20-
use rustc_hir::def::DefKind;
20+
use rustc_hir::def::{DefKind, MacroKinds};
2121
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
2222
use rustc_hir::{ConstStability, StabilityLevel, StableSince};
23-
use rustc_metadata::creader::{CStore, LoadedMacro};
23+
use rustc_metadata::creader::CStore;
2424
use rustc_middle::ty::{self, TyCtxt, TypingMode};
2525
use rustc_span::symbol::kw;
2626
use rustc_span::{Symbol, sym};
@@ -358,27 +358,23 @@ fn generate_macro_def_id_path(
358358
let crate_name = tcx.crate_name(def_id.krate);
359359
let cache = cx.cache();
360360

361-
let fqp = clean::inline::item_relative_path(tcx, def_id);
362-
let mut relative = fqp.iter().copied();
363361
let cstore = CStore::from_tcx(tcx);
364362
// We need this to prevent a `panic` when this function is used from intra doc links...
365363
if !cstore.has_crate_data(def_id.krate) {
366364
debug!("No data for crate {crate_name}");
367365
return Err(HrefError::NotInExternalCache);
368366
}
369-
// Check to see if it is a macro 2.0 or built-in macro.
370-
// More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
371-
let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) {
372-
// If `def.macro_rules` is `true`, then it's not a macro 2.0.
373-
LoadedMacro::MacroDef { def, .. } => !def.macro_rules,
374-
_ => false,
367+
let DefKind::Macro(kinds) = tcx.def_kind(def_id) else {
368+
unreachable!();
375369
};
376-
377-
let mut path = if is_macro_2 {
378-
once(crate_name).chain(relative).collect()
370+
let item_type = if kinds == MacroKinds::DERIVE {
371+
ItemType::ProcDerive
372+
} else if kinds == MacroKinds::ATTR {
373+
ItemType::ProcAttribute
379374
} else {
380-
vec![crate_name, relative.next_back().unwrap()]
375+
ItemType::Macro
381376
};
377+
let mut path = clean::inline::get_item_path(tcx, def_id, item_type);
382378
if path.len() < 2 {
383379
// The minimum we can have is the crate name followed by the macro name. If shorter, then
384380
// it means that `relative` was empty, which is an error.
@@ -387,7 +383,7 @@ fn generate_macro_def_id_path(
387383
}
388384

389385
if let Some(last) = path.last_mut() {
390-
*last = Symbol::intern(&format!("macro.{last}.html"));
386+
*last = Symbol::intern(&format!("{}.{last}.html", item_type.as_str()));
391387
}
392388

393389
let url = match cache.extern_locations[&def_id.krate] {
@@ -408,7 +404,7 @@ fn generate_macro_def_id_path(
408404
return Err(HrefError::NotInExternalCache);
409405
}
410406
};
411-
Ok((url, ItemType::Macro, fqp))
407+
Ok((url, item_type, path))
412408
}
413409

414410
fn generate_item_def_id_path(

0 commit comments

Comments
 (0)