Skip to content

Commit d214402

Browse files
authored
Rollup merge of #106412 - GuillaumeGomez:fix-links-to-primitive-rustdoc-json, r=aDotInTheVoid
Fix link generation for local primitive types in rustdoc JSON output Fixes #104064. As mentioned in the issue, I'm not super happy about this fix which is more a hack rather than a sound-proof solution. However I couldn't find a better way to fix it. r? `@aDotInTheVoid`
2 parents 5eb9698 + c9ebd73 commit d214402

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

src/librustdoc/json/conversions.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use std::convert::From;
88
use std::fmt;
99

1010
use rustc_ast::ast;
11-
use rustc_hir::{def::CtorKind, def_id::DefId};
11+
use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
1212
use rustc_middle::ty::{self, TyCtxt};
13+
use rustc_span::symbol::sym;
1314
use rustc_span::{Pos, Symbol};
1415
use rustc_target::spec::abi::Abi as RustcAbi;
1516

@@ -217,13 +218,27 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
217218

218219
impl<'a> fmt::Display for DisplayDefId<'a> {
219220
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220-
let name = match self.2 {
221+
let DisplayDefId(def_id, tcx, name) = self;
222+
let name = match name {
221223
Some(name) => format!(":{}", name.as_u32()),
222-
None => self
223-
.1
224-
.opt_item_name(self.0)
225-
.map(|n| format!(":{}", n.as_u32()))
226-
.unwrap_or_default(),
224+
None => {
225+
// We need this workaround because primitive types' DefId actually refers to
226+
// their parent module, which isn't present in the output JSON items. So
227+
// instead, we directly get the primitive symbol and convert it to u32 to
228+
// generate the ID.
229+
if matches!(tcx.def_kind(def_id), DefKind::Mod) &&
230+
let Some(prim) = tcx.get_attrs(*def_id, sym::doc)
231+
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
232+
.filter(|attr| attr.has_name(sym::primitive))
233+
.find_map(|attr| attr.value_str()) {
234+
format!(":{}", prim.as_u32())
235+
} else {
236+
tcx
237+
.opt_item_name(*def_id)
238+
.map(|n| format!(":{}", n.as_u32()))
239+
.unwrap_or_default()
240+
}
241+
}
227242
};
228243
write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
229244
}
@@ -237,7 +252,7 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
237252
ItemId::Auto { for_, trait_ } => {
238253
Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
239254
}
240-
ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
255+
ItemId::Primitive(_, _) => unreachable!(),
241256
}
242257
}
243258

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/104064>.
2+
3+
#![feature(no_core)]
4+
#![feature(rustc_attrs)]
5+
#![feature(rustdoc_internals)]
6+
#![no_core]
7+
#![rustc_coherence_is_core]
8+
9+
//! Link to [i32][prim@i32] [i64][prim@i64]
10+
11+
#[doc(primitive = "i32")]
12+
mod prim_i32 {}
13+
14+
// @set local_i32 = "$.index[*][?(@.name=='i32')].id"
15+
16+
// @has "$.index[*][?(@.name=='local_primitive')]"
17+
// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32
18+
// @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
19+
20+
// Let's ensure the `prim_i32` module isn't present in the output JSON:
21+
// @!has "$.index[*][?(@.name=='prim_i32')]"

0 commit comments

Comments
 (0)