@@ -38,7 +38,7 @@ impl JsonRenderer<'_> {
3838 Some ( UrlFragment :: UserWritten ( _) ) | None => * page_id,
3939 } ;
4040
41- ( link. clone ( ) , from_item_id ( id. into ( ) , self . tcx ) )
41+ ( link. clone ( ) , id_from_item_default ( id. into ( ) , self . tcx ) )
4242 } )
4343 . collect ( ) ;
4444 let docs = item. attrs . collapsed_doc_value ( ) ;
@@ -50,7 +50,8 @@ impl JsonRenderer<'_> {
5050 . collect ( ) ;
5151 let span = item. span ( self . tcx ) ;
5252 let visibility = item. visibility ( self . tcx ) ;
53- let clean:: Item { name, attrs : _, kind : _, item_id, cfg : _, .. } = item;
53+ let clean:: Item { name, item_id, .. } = item;
54+ let id = id_from_item ( & item, self . tcx ) ;
5455 let inner = match * item. kind {
5556 clean:: KeywordItem => return None ,
5657 clean:: StrippedItem ( ref inner) => {
@@ -69,7 +70,7 @@ impl JsonRenderer<'_> {
6970 _ => from_clean_item ( item, self . tcx ) ,
7071 } ;
7172 Some ( Item {
72- id : from_item_id_with_name ( item_id , self . tcx , name ) ,
73+ id,
7374 crate_id : item_id. krate ( ) . as_u32 ( ) ,
7475 name : name. map ( |sym| sym. to_string ( ) ) ,
7576 span : span. and_then ( |span| self . convert_span ( span) ) ,
@@ -107,7 +108,7 @@ impl JsonRenderer<'_> {
107108 Some ( ty:: Visibility :: Public ) => Visibility :: Public ,
108109 Some ( ty:: Visibility :: Restricted ( did) ) if did. is_crate_root ( ) => Visibility :: Crate ,
109110 Some ( ty:: Visibility :: Restricted ( did) ) => Visibility :: Restricted {
110- parent : from_item_id ( did. into ( ) , self . tcx ) ,
111+ parent : id_from_item_default ( did. into ( ) , self . tcx ) ,
111112 path : self . tcx . def_path ( did) . to_string_no_crate_verbose ( ) ,
112113 } ,
113114 }
@@ -204,21 +205,42 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
204205 }
205206}
206207
207- /// It generates an ID as follows:
208- ///
209- /// `CRATE_ID:ITEM_ID[:NAME_ID]` (if there is no name, NAME_ID is not generated).
210- pub ( crate ) fn from_item_id ( item_id : ItemId , tcx : TyCtxt < ' _ > ) -> Id {
211- from_item_id_with_name ( item_id, tcx, None )
208+ #[ inline]
209+ pub ( crate ) fn id_from_item_default ( item_id : ItemId , tcx : TyCtxt < ' _ > ) -> Id {
210+ id_from_item_inner ( item_id, tcx, None , None )
212211}
213212
214- // FIXME: this function (and appending the name at the end of the ID) should be removed when
215- // reexports are not inlined anymore for json format. It should be done in #93518.
216- pub ( crate ) fn from_item_id_with_name ( item_id : ItemId , tcx : TyCtxt < ' _ > , name : Option < Symbol > ) -> Id {
217- struct DisplayDefId < ' a > ( DefId , TyCtxt < ' a > , Option < Symbol > ) ;
213+ /// It generates an ID as follows:
214+ ///
215+ /// `CRATE_ID:ITEM_ID[:NAME_ID][-EXTRA]`:
216+ /// * If there is no `name`, `NAME_ID` is not generated.
217+ /// * If there is no `extra`, `EXTRA` is not generated.
218+ ///
219+ /// * `name` is the item's name if available (it's not for impl blocks for example).
220+ /// * `extra` is used for reexports: it contains the ID of the reexported item. It is used to allow
221+ /// to have items with the same name but different types to both appear in the generated JSON.
222+ pub ( crate ) fn id_from_item_inner (
223+ item_id : ItemId ,
224+ tcx : TyCtxt < ' _ > ,
225+ name : Option < Symbol > ,
226+ extra : Option < & Id > ,
227+ ) -> Id {
228+ struct DisplayDefId < ' a , ' b > ( DefId , TyCtxt < ' a > , Option < & ' b Id > , Option < Symbol > ) ;
218229
219- impl < ' a > fmt:: Display for DisplayDefId < ' a > {
230+ impl < ' a , ' b > fmt:: Display for DisplayDefId < ' a , ' b > {
220231 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
221- let DisplayDefId ( def_id, tcx, name) = self ;
232+ let DisplayDefId ( def_id, tcx, extra, name) = self ;
233+ // We need this workaround because primitive types' DefId actually refers to
234+ // their parent module, which isn't present in the output JSON items. So
235+ // instead, we directly get the primitive symbol and convert it to u32 to
236+ // generate the ID.
237+ let s;
238+ let extra = if let Some ( e) = extra {
239+ s = format ! ( "-{}" , e. 0 ) ;
240+ & s
241+ } else {
242+ ""
243+ } ;
222244 let name = match name {
223245 Some ( name) => format ! ( ":{}" , name. as_u32( ) ) ,
224246 None => {
@@ -240,18 +262,33 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
240262 }
241263 }
242264 } ;
243- write ! ( f, "{}:{}{} " , self . 0 . krate. as_u32( ) , u32 :: from( self . 0 . index) , name )
265+ write ! ( f, "{}:{}{name}{extra} " , def_id . krate. as_u32( ) , u32 :: from( def_id . index) )
244266 }
245267 }
246268
247269 match item_id {
248- ItemId :: DefId ( did) => Id ( format ! ( "{}" , DisplayDefId ( did, tcx, name) ) ) ,
249- ItemId :: Blanket { for_, impl_id } => {
250- Id ( format ! ( "b:{}-{}" , DisplayDefId ( impl_id, tcx, None ) , DisplayDefId ( for_, tcx, name) ) )
251- }
252- ItemId :: Auto { for_, trait_ } => {
253- Id ( format ! ( "a:{}-{}" , DisplayDefId ( trait_, tcx, None ) , DisplayDefId ( for_, tcx, name) ) )
270+ ItemId :: DefId ( did) => Id ( format ! ( "{}" , DisplayDefId ( did, tcx, extra, name) ) ) ,
271+ ItemId :: Blanket { for_, impl_id } => Id ( format ! (
272+ "b:{}-{}" ,
273+ DisplayDefId ( impl_id, tcx, None , None ) ,
274+ DisplayDefId ( for_, tcx, extra, name)
275+ ) ) ,
276+ ItemId :: Auto { for_, trait_ } => Id ( format ! (
277+ "a:{}-{}" ,
278+ DisplayDefId ( trait_, tcx, None , None ) ,
279+ DisplayDefId ( for_, tcx, extra, name)
280+ ) ) ,
281+ }
282+ }
283+
284+ pub ( crate ) fn id_from_item ( item : & clean:: Item , tcx : TyCtxt < ' _ > ) -> Id {
285+ match * item. kind {
286+ clean:: ItemKind :: ImportItem ( ref import) => {
287+ let extra =
288+ import. source . did . map ( ItemId :: from) . map ( |i| id_from_item_inner ( i, tcx, None , None ) ) ;
289+ id_from_item_inner ( item. item_id , tcx, item. name , extra. as_ref ( ) )
254290 }
291+ _ => id_from_item_inner ( item. item_id , tcx, item. name , None ) ,
255292 }
256293}
257294
@@ -525,7 +562,7 @@ impl FromWithTcx<clean::Path> for Path {
525562 fn from_tcx ( path : clean:: Path , tcx : TyCtxt < ' _ > ) -> Path {
526563 Path {
527564 name : path. whole_name ( ) ,
528- id : from_item_id ( path. def_id ( ) . into ( ) , tcx) ,
565+ id : id_from_item_default ( path. def_id ( ) . into ( ) , tcx) ,
529566 args : path. segments . last ( ) . map ( |args| Box :: new ( args. clone ( ) . args . into_tcx ( tcx) ) ) ,
530567 }
531568 }
@@ -702,7 +739,7 @@ impl FromWithTcx<clean::Import> for Import {
702739 Import {
703740 source : import. source . path . whole_name ( ) ,
704741 name,
705- id : import. source . did . map ( ItemId :: from) . map ( |i| from_item_id ( i, tcx) ) ,
742+ id : import. source . did . map ( ItemId :: from) . map ( |i| id_from_item_default ( i, tcx) ) ,
706743 glob,
707744 }
708745 }
@@ -791,7 +828,7 @@ fn ids(items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>) -> Vec<Id>
791828 items
792829 . into_iter ( )
793830 . filter ( |x| !x. is_stripped ( ) && !x. is_keyword ( ) )
794- . map ( |i| from_item_id_with_name ( i . item_id , tcx, i . name ) )
831+ . map ( |i| id_from_item ( & i , tcx) )
795832 . collect ( )
796833}
797834
@@ -801,12 +838,10 @@ fn ids_keeping_stripped(
801838) -> Vec < Option < Id > > {
802839 items
803840 . into_iter ( )
804- . map ( |i| {
805- if !i. is_stripped ( ) && !i. is_keyword ( ) {
806- Some ( from_item_id_with_name ( i. item_id , tcx, i. name ) )
807- } else {
808- None
809- }
810- } )
841+ . map (
842+ |i| {
843+ if !i. is_stripped ( ) && !i. is_keyword ( ) { Some ( id_from_item ( & i, tcx) ) } else { None }
844+ } ,
845+ )
811846 . collect ( )
812847}
0 commit comments