Skip to content

Commit f22f743

Browse files
authored
Rollup merge of #97599 - GuillaumeGomez:reexport-json, r=CraftSpider
Fix JSON reexport ICE Fixes #97432. The problem was that the ID was conflicting because the reexports have the same one. To fix it, I "extended" it by adding the `Symbol` into it as well. r? `@notriddle`
2 parents 15bf62b + 5adca73 commit f22f743

File tree

3 files changed

+83
-35
lines changed

3 files changed

+83
-35
lines changed

src/librustdoc/json/conversions.rs

+50-27
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::fmt;
1010
use rustc_ast::ast;
1111
use rustc_hir::{def::CtorKind, def_id::DefId};
1212
use rustc_middle::ty::{self, TyCtxt};
13-
use rustc_span::Pos;
13+
use rustc_span::{Pos, Symbol};
1414
use rustc_target::spec::abi::Abi as RustcAbi;
1515

1616
use rustdoc_json_types::*;
@@ -29,7 +29,9 @@ impl JsonRenderer<'_> {
2929
.get(&item.item_id)
3030
.into_iter()
3131
.flatten()
32-
.map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
32+
.map(|clean::ItemLink { link, did, .. }| {
33+
(link.clone(), from_item_id((*did).into(), self.tcx))
34+
})
3335
.collect();
3436
let docs = item.attrs.collapsed_doc_value();
3537
let attrs = item
@@ -45,7 +47,7 @@ impl JsonRenderer<'_> {
4547
_ => from_clean_item(item, self.tcx),
4648
};
4749
Some(Item {
48-
id: from_item_id(item_id),
50+
id: from_item_id_with_name(item_id, self.tcx, name),
4951
crate_id: item_id.krate().as_u32(),
5052
name: name.map(|sym| sym.to_string()),
5153
span: self.convert_span(span),
@@ -84,7 +86,7 @@ impl JsonRenderer<'_> {
8486
Inherited => Visibility::Default,
8587
Restricted(did) if did.is_crate_root() => Visibility::Crate,
8688
Restricted(did) => Visibility::Restricted {
87-
parent: from_item_id(did.into()),
89+
parent: from_item_id(did.into(), self.tcx),
8890
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
8991
},
9092
}
@@ -173,22 +175,39 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
173175
}
174176
}
175177

176-
pub(crate) fn from_item_id(item_id: ItemId) -> Id {
177-
struct DisplayDefId(DefId);
178+
/// It generates an ID as follows:
179+
///
180+
/// `CRATE_ID:ITEM_ID[:NAME_ID]` (if there is no name, NAME_ID is not generated).
181+
pub(crate) fn from_item_id(item_id: ItemId, tcx: TyCtxt<'_>) -> Id {
182+
from_item_id_with_name(item_id, tcx, None)
183+
}
184+
185+
// FIXME: this function (and appending the name at the end of the ID) should be removed when
186+
// reexports are not inlined anymore for json format. It should be done in #93518.
187+
pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Option<Symbol>) -> Id {
188+
struct DisplayDefId<'a>(DefId, TyCtxt<'a>, Option<Symbol>);
178189

179-
impl fmt::Display for DisplayDefId {
190+
impl<'a> fmt::Display for DisplayDefId<'a> {
180191
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181-
write!(f, "{}:{}", self.0.krate.as_u32(), u32::from(self.0.index))
192+
let name = match self.2 {
193+
Some(name) => format!(":{}", name.as_u32()),
194+
None => self
195+
.1
196+
.opt_item_name(self.0)
197+
.map(|n| format!(":{}", n.as_u32()))
198+
.unwrap_or_default(),
199+
};
200+
write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
182201
}
183202
}
184203

185204
match item_id {
186-
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
205+
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, name))),
187206
ItemId::Blanket { for_, impl_id } => {
188-
Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
207+
Id(format!("b:{}-{}", DisplayDefId(impl_id, tcx, None), DisplayDefId(for_, tcx, name)))
189208
}
190209
ItemId::Auto { for_, trait_ } => {
191-
Id(format!("a:{}-{}", DisplayDefId(trait_), DisplayDefId(for_)))
210+
Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
192211
}
193212
ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
194213
}
@@ -201,7 +220,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
201220
let header = item.fn_header(tcx);
202221

203222
match *item.kind {
204-
ModuleItem(m) => ItemEnum::Module(Module { is_crate, items: ids(m.items) }),
223+
ModuleItem(m) => ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx) }),
205224
ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
206225
StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
207226
UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
@@ -255,7 +274,7 @@ impl FromWithTcx<clean::Struct> for Struct {
255274
struct_type: from_ctor_kind(struct_type),
256275
generics: generics.into_tcx(tcx),
257276
fields_stripped,
258-
fields: ids(fields),
277+
fields: ids(fields, tcx),
259278
impls: Vec::new(), // Added in JsonRenderer::item
260279
}
261280
}
@@ -268,7 +287,7 @@ impl FromWithTcx<clean::Union> for Union {
268287
Union {
269288
generics: generics.into_tcx(tcx),
270289
fields_stripped,
271-
fields: ids(fields),
290+
fields: ids(fields, tcx),
272291
impls: Vec::new(), // Added in JsonRenderer::item
273292
}
274293
}
@@ -413,7 +432,7 @@ impl FromWithTcx<clean::Type> for Type {
413432
match ty {
414433
clean::Type::Path { path } => Type::ResolvedPath {
415434
name: path.whole_name(),
416-
id: from_item_id(path.def_id().into()),
435+
id: from_item_id(path.def_id().into(), tcx),
417436
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
418437
param_names: Vec::new(),
419438
},
@@ -422,7 +441,7 @@ impl FromWithTcx<clean::Type> for Type {
422441

423442
Type::ResolvedPath {
424443
name: first_trait.whole_name(),
425-
id: from_item_id(first_trait.def_id().into()),
444+
id: from_item_id(first_trait.def_id().into(), tcx),
426445
args: first_trait
427446
.segments
428447
.last()
@@ -517,7 +536,7 @@ impl FromWithTcx<clean::Trait> for Trait {
517536
Trait {
518537
is_auto,
519538
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
520-
items: ids(items),
539+
items: ids(items, tcx),
521540
generics: generics.into_tcx(tcx),
522541
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
523542
implementations: Vec::new(), // Added in JsonRenderer::item
@@ -550,7 +569,7 @@ impl FromWithTcx<clean::Impl> for Impl {
550569
.collect(),
551570
trait_,
552571
for_: for_.into_tcx(tcx),
553-
items: ids(items),
572+
items: ids(items, tcx),
554573
negative: negative_polarity,
555574
synthetic,
556575
blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
@@ -593,21 +612,21 @@ impl FromWithTcx<clean::Enum> for Enum {
593612
Enum {
594613
generics: generics.into_tcx(tcx),
595614
variants_stripped,
596-
variants: ids(variants),
615+
variants: ids(variants, tcx),
597616
impls: Vec::new(), // Added in JsonRenderer::item
598617
}
599618
}
600619
}
601620

602621
impl FromWithTcx<clean::VariantStruct> for Struct {
603-
fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self {
622+
fn from_tcx(struct_: clean::VariantStruct, tcx: TyCtxt<'_>) -> Self {
604623
let fields_stripped = struct_.has_stripped_entries();
605624
let clean::VariantStruct { struct_type, fields } = struct_;
606625
Struct {
607626
struct_type: from_ctor_kind(struct_type),
608627
generics: Default::default(),
609628
fields_stripped,
610-
fields: ids(fields),
629+
fields: ids(fields, tcx),
611630
impls: Vec::new(),
612631
}
613632
}
@@ -630,25 +649,25 @@ impl FromWithTcx<clean::Variant> for Variant {
630649
})
631650
.collect(),
632651
),
633-
Struct(s) => Variant::Struct(ids(s.fields)),
652+
Struct(s) => Variant::Struct(ids(s.fields, tcx)),
634653
}
635654
}
636655
}
637656

638657
impl FromWithTcx<clean::Import> for Import {
639-
fn from_tcx(import: clean::Import, _tcx: TyCtxt<'_>) -> Self {
658+
fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
640659
use clean::ImportKind::*;
641660
match import.kind {
642661
Simple(s) => Import {
643662
source: import.source.path.whole_name(),
644663
name: s.to_string(),
645-
id: import.source.did.map(ItemId::from).map(from_item_id),
664+
id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
646665
glob: false,
647666
},
648667
Glob => Import {
649668
source: import.source.path.whole_name(),
650669
name: import.source.path.last().to_string(),
651-
id: import.source.did.map(ItemId::from).map(from_item_id),
670+
id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
652671
glob: true,
653672
},
654673
}
@@ -742,6 +761,10 @@ impl FromWithTcx<ItemType> for ItemKind {
742761
}
743762
}
744763

745-
fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
746-
items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.item_id)).collect()
764+
fn ids(items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>) -> Vec<Id> {
765+
items
766+
.into_iter()
767+
.filter(|x| !x.is_stripped())
768+
.map(|i| from_item_id_with_name(i.item_id, tcx, i.name))
769+
.collect()
747770
}

src/librustdoc/json/mod.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_data_structures::fx::FxHashMap;
1616
use rustc_hir::def_id::DefId;
1717
use rustc_middle::ty::TyCtxt;
1818
use rustc_session::Session;
19+
use rustc_span::def_id::LOCAL_CRATE;
1920

2021
use rustdoc_json_types as types;
2122

@@ -25,7 +26,7 @@ use crate::docfs::PathError;
2526
use crate::error::Error;
2627
use crate::formats::cache::Cache;
2728
use crate::formats::FormatRenderer;
28-
use crate::json::conversions::{from_item_id, IntoWithTcx};
29+
use crate::json::conversions::{from_item_id, from_item_id_with_name, IntoWithTcx};
2930
use crate::{clean, try_err};
3031

3132
#[derive(Clone)]
@@ -54,7 +55,7 @@ impl<'tcx> JsonRenderer<'tcx> {
5455
.map(|i| {
5556
let item = &i.impl_item;
5657
self.item(item.clone()).unwrap();
57-
from_item_id(item.item_id)
58+
from_item_id_with_name(item.item_id, self.tcx, item.name)
5859
})
5960
.collect()
6061
})
@@ -86,7 +87,7 @@ impl<'tcx> JsonRenderer<'tcx> {
8687

8788
if item.item_id.is_local() || is_primitive_impl {
8889
self.item(item.clone()).unwrap();
89-
Some(from_item_id(item.item_id))
90+
Some(from_item_id_with_name(item.item_id, self.tcx, item.name))
9091
} else {
9192
None
9293
}
@@ -105,10 +106,11 @@ impl<'tcx> JsonRenderer<'tcx> {
105106
if !id.is_local() {
106107
let trait_item = &trait_item.trait_;
107108
trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
109+
let item_id = from_item_id(id.into(), self.tcx);
108110
Some((
109-
from_item_id(id.into()),
111+
item_id.clone(),
110112
types::Item {
111-
id: from_item_id(id.into()),
113+
id: item_id,
112114
crate_id: id.krate.as_u32(),
113115
name: self
114116
.cache
@@ -176,6 +178,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
176178
// Flatten items that recursively store other items
177179
item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
178180

181+
let name = item.name;
179182
let item_id = item.item_id;
180183
if let Some(mut new_item) = self.convert_item(item) {
181184
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
@@ -187,7 +190,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
187190
} else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
188191
u.impls = self.get_impls(item_id.expect_def_id())
189192
}
190-
let removed = self.index.borrow_mut().insert(from_item_id(item_id), new_item.clone());
193+
let removed = self
194+
.index
195+
.borrow_mut()
196+
.insert(from_item_id_with_name(item_id, self.tcx, name), new_item.clone());
191197

192198
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
193199
// to make sure the items are unique. The main place this happens is when an item, is
@@ -211,13 +217,15 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
211217
self.get_impls(*primitive);
212218
}
213219

220+
let e = ExternalCrate { crate_num: LOCAL_CRATE };
221+
214222
let mut index = (*self.index).clone().into_inner();
215223
index.extend(self.get_trait_items());
216224
// This needs to be the default HashMap for compatibility with the public interface for
217225
// rustdoc-json-types
218226
#[allow(rustc::default_hash_types)]
219227
let output = types::Crate {
220-
root: types::Id(String::from("0:0")),
228+
root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())),
221229
crate_version: self.cache.crate_version.clone(),
222230
includes_private: self.cache.document_private,
223231
index: index.into_iter().collect(),
@@ -229,7 +237,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
229237
.chain(self.cache.external_paths.clone().into_iter())
230238
.map(|(k, (path, kind))| {
231239
(
232-
from_item_id(k.into()),
240+
from_item_id(k.into(), self.tcx),
233241
types::ItemSummary {
234242
crate_id: k.krate.as_u32(),
235243
path: path.iter().map(|s| s.to_string()).collect(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Regression test for https://github.com/rust-lang/rust/issues/97432.
2+
3+
#![feature(no_core)]
4+
#![no_std]
5+
#![no_core]
6+
7+
// @has same_type_reexported_more_than_once.json
8+
// @set trait_id = - "$.index[*][?(@.name=='Trait')].id"
9+
// @has - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $trait_id
10+
pub use inner::Trait;
11+
// @set reexport_id = - "$.index[*][?(@.name=='Reexport')].id"
12+
// @has - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id
13+
pub use inner::Trait as Reexport;
14+
15+
mod inner {
16+
pub trait Trait {}
17+
}

0 commit comments

Comments
 (0)