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 https://github.com/rust-lang/rust/issues/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`
This commit is contained in:
Matthias Krüger 2023-01-04 23:39:50 +01:00 committed by GitHub
commit d214402128
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 8 deletions

View File

@ -8,8 +8,9 @@ use std::convert::From;
use std::fmt; use std::fmt;
use rustc_ast::ast; use rustc_ast::ast;
use rustc_hir::{def::CtorKind, def_id::DefId}; use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::{Pos, Symbol}; use rustc_span::{Pos, Symbol};
use rustc_target::spec::abi::Abi as RustcAbi; use rustc_target::spec::abi::Abi as RustcAbi;
@ -217,13 +218,27 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
impl<'a> fmt::Display for DisplayDefId<'a> { impl<'a> fmt::Display for DisplayDefId<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self.2 { let DisplayDefId(def_id, tcx, name) = self;
let name = match name {
Some(name) => format!(":{}", name.as_u32()), Some(name) => format!(":{}", name.as_u32()),
None => self None => {
.1 // We need this workaround because primitive types' DefId actually refers to
.opt_item_name(self.0) // their parent module, which isn't present in the output JSON items. So
.map(|n| format!(":{}", n.as_u32())) // instead, we directly get the primitive symbol and convert it to u32 to
.unwrap_or_default(), // generate the ID.
if matches!(tcx.def_kind(def_id), DefKind::Mod) &&
let Some(prim) = tcx.get_attrs(*def_id, sym::doc)
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
.filter(|attr| attr.has_name(sym::primitive))
.find_map(|attr| attr.value_str()) {
format!(":{}", prim.as_u32())
} else {
tcx
.opt_item_name(*def_id)
.map(|n| format!(":{}", n.as_u32()))
.unwrap_or_default()
}
}
}; };
write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name) write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
} }
@ -237,7 +252,7 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
ItemId::Auto { for_, trait_ } => { ItemId::Auto { for_, trait_ } => {
Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name))) Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
} }
ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())), ItemId::Primitive(_, _) => unreachable!(),
} }
} }

View File

@ -0,0 +1,21 @@
// Regression test for <https://github.com/rust-lang/rust/issues/104064>.
#![feature(no_core)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![no_core]
#![rustc_coherence_is_core]
//! Link to [i32][prim@i32] [i64][prim@i64]
#[doc(primitive = "i32")]
mod prim_i32 {}
// @set local_i32 = "$.index[*][?(@.name=='i32')].id"
// @has "$.index[*][?(@.name=='local_primitive')]"
// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32
// @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
// Let's ensure the `prim_i32` module isn't present in the output JSON:
// @!has "$.index[*][?(@.name=='prim_i32')]"