Skip to content

Commit beb2f36

Browse files
Fix panic by checking if CStore has the crate data we want before actually querying it
1 parent 987c731 commit beb2f36

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

compiler/rustc_metadata/src/creader.rs

+4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ impl CStore {
133133
CrateNum::new(self.metas.len() - 1)
134134
}
135135

136+
pub fn has_crate_data(&self, cnum: CrateNum) -> bool {
137+
self.metas[cnum].is_some()
138+
}
139+
136140
pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
137141
let cdata = self.metas[cnum]
138142
.as_ref()

src/librustdoc/html/format.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ fn generate_macro_def_id_path(
565565
def_id: DefId,
566566
cx: &Context<'_>,
567567
root_path: Option<&str>,
568-
) -> (String, ItemType, Vec<Symbol>) {
568+
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
569569
let tcx = cx.shared.tcx;
570570
let crate_name = tcx.crate_name(def_id.krate).to_string();
571571
let cache = cx.cache();
@@ -583,9 +583,15 @@ fn generate_macro_def_id_path(
583583
})
584584
.collect();
585585
let relative = fqp.iter().map(|elem| elem.to_string());
586+
let cstore = CStore::from_tcx(tcx);
587+
// We need this to prevent a `panic` when this function is used from intra doc links...
588+
if !cstore.has_crate_data(def_id.krate) {
589+
debug!("No data for crate {}", crate_name);
590+
return Err(HrefError::NotInExternalCache);
591+
}
586592
// Check to see if it is a macro 2.0 or built-in macro.
587593
// More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
588-
let is_macro_2 = match CStore::from_tcx(tcx).load_macro_untracked(def_id, tcx.sess) {
594+
let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx.sess) {
589595
LoadedMacro::MacroDef(def, _) => {
590596
// If `ast_def.macro_rules` is `true`, then it's not a macro 2.0.
591597
matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules)
@@ -601,7 +607,8 @@ fn generate_macro_def_id_path(
601607
if path.len() < 2 {
602608
// The minimum we can have is the crate name followed by the macro name. If shorter, then
603609
// it means that that `relative` was empty, which is an error.
604-
panic!("macro path cannot be empty!");
610+
debug!("macro path cannot be empty!");
611+
return Err(HrefError::NotInExternalCache);
605612
}
606613

607614
if let Some(last) = path.last_mut() {
@@ -618,10 +625,11 @@ fn generate_macro_def_id_path(
618625
format!("{}{}/{}", root_path.unwrap_or(""), crate_name, path.join("/"))
619626
}
620627
ExternalLocation::Unknown => {
621-
panic!("crate {} not in cache when linkifying macros", crate_name)
628+
debug!("crate {} not in cache when linkifying macros", crate_name);
629+
return Err(HrefError::NotInExternalCache);
622630
}
623631
};
624-
(url, ItemType::Macro, fqp)
632+
Ok((url, ItemType::Macro, fqp))
625633
}
626634

627635
pub(crate) fn href_with_root_path(
@@ -680,7 +688,7 @@ pub(crate) fn href_with_root_path(
680688
},
681689
)
682690
} else if matches!(def_kind, DefKind::Macro(_)) {
683-
return Ok(generate_macro_def_id_path(did, cx, root_path));
691+
return generate_macro_def_id_path(did, cx, root_path);
684692
} else {
685693
return Err(HrefError::NotInExternalCache);
686694
}

0 commit comments

Comments
 (0)