@@ -59,10 +59,13 @@ pub(crate) fn build_index<'tcx>(
59
59
cache : & mut Cache ,
60
60
tcx : TyCtxt < ' tcx > ,
61
61
) -> SerializedSearchIndex {
62
+ // Maps from ID to position in the `crate_paths` array.
62
63
let mut itemid_to_pathid = FxHashMap :: default ( ) ;
63
64
let mut primitives = FxHashMap :: default ( ) ;
64
65
let mut associated_types = FxHashMap :: default ( ) ;
65
- let mut crate_paths = vec ! [ ] ;
66
+
67
+ // item type, display path, re-exported internal path
68
+ let mut crate_paths: Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > = vec ! [ ] ;
66
69
67
70
// Attach all orphan items to the type's definition if the type
68
71
// has since been learned.
@@ -72,11 +75,13 @@ pub(crate) fn build_index<'tcx>(
72
75
let desc = short_markdown_summary ( & item. doc_value ( ) , & item. link_names ( cache) ) ;
73
76
cache. search_index . push ( IndexItem {
74
77
ty : item. type_ ( ) ,
78
+ defid : item. item_id . as_def_id ( ) ,
75
79
name : item. name . unwrap ( ) ,
76
80
path : join_with_double_colon ( & fqp[ ..fqp. len ( ) - 1 ] ) ,
77
81
desc,
78
82
parent : Some ( parent) ,
79
83
parent_idx : None ,
84
+ exact_path : None ,
80
85
impl_id,
81
86
search_type : get_function_type_for_search (
82
87
item,
@@ -126,17 +131,22 @@ pub(crate) fn build_index<'tcx>(
126
131
map : & mut FxHashMap < F , isize > ,
127
132
itemid : F ,
128
133
lastpathid : & mut isize ,
129
- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
134
+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
130
135
item_type : ItemType ,
131
136
path : & [ Symbol ] ,
137
+ exact_path : Option < & [ Symbol ] > ,
132
138
) -> RenderTypeId {
133
139
match map. entry ( itemid) {
134
140
Entry :: Occupied ( entry) => RenderTypeId :: Index ( * entry. get ( ) ) ,
135
141
Entry :: Vacant ( entry) => {
136
142
let pathid = * lastpathid;
137
143
entry. insert ( pathid) ;
138
144
* lastpathid += 1 ;
139
- crate_paths. push ( ( item_type, path. to_vec ( ) ) ) ;
145
+ crate_paths. push ( (
146
+ item_type,
147
+ path. to_vec ( ) ,
148
+ exact_path. map ( |path| path. to_vec ( ) ) ,
149
+ ) ) ;
140
150
RenderTypeId :: Index ( pathid)
141
151
}
142
152
}
@@ -149,21 +159,32 @@ pub(crate) fn build_index<'tcx>(
149
159
primitives : & mut FxHashMap < Symbol , isize > ,
150
160
associated_types : & mut FxHashMap < Symbol , isize > ,
151
161
lastpathid : & mut isize ,
152
- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
162
+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
153
163
) -> Option < RenderTypeId > {
154
- let Cache { ref paths, ref external_paths, .. } = * cache;
164
+ let Cache { ref paths, ref external_paths, ref exact_paths , .. } = * cache;
155
165
match id {
156
166
RenderTypeId :: DefId ( defid) => {
157
167
if let Some ( & ( ref fqp, item_type) ) =
158
168
paths. get ( & defid) . or_else ( || external_paths. get ( & defid) )
159
169
{
170
+ let exact_fqp = exact_paths
171
+ . get ( & defid)
172
+ . or_else ( || external_paths. get ( & defid) . map ( |& ( ref fqp, _) | fqp) )
173
+ // Re-exports only count if the name is exactly the same.
174
+ // This is a size optimization, since it means we only need
175
+ // to store the name once (and the path is re-used for everything
176
+ // exported from this same module). It's also likely to Do
177
+ // What I Mean, since if a re-export changes the name, it might
178
+ // also be a change in semantic meaning.
179
+ . filter ( |fqp| fqp. last ( ) == fqp. last ( ) ) ;
160
180
Some ( insert_into_map (
161
181
itemid_to_pathid,
162
182
ItemId :: DefId ( defid) ,
163
183
lastpathid,
164
184
crate_paths,
165
185
item_type,
166
186
fqp,
187
+ exact_fqp. map ( |x| & x[ ..] ) . filter ( |exact_fqp| exact_fqp != fqp) ,
167
188
) )
168
189
} else {
169
190
None
@@ -178,6 +199,7 @@ pub(crate) fn build_index<'tcx>(
178
199
crate_paths,
179
200
ItemType :: Primitive ,
180
201
& [ sym] ,
202
+ None ,
181
203
) )
182
204
}
183
205
RenderTypeId :: Index ( _) => Some ( id) ,
@@ -188,6 +210,7 @@ pub(crate) fn build_index<'tcx>(
188
210
crate_paths,
189
211
ItemType :: AssocType ,
190
212
& [ sym] ,
213
+ None ,
191
214
) ) ,
192
215
}
193
216
}
@@ -199,7 +222,7 @@ pub(crate) fn build_index<'tcx>(
199
222
primitives : & mut FxHashMap < Symbol , isize > ,
200
223
associated_types : & mut FxHashMap < Symbol , isize > ,
201
224
lastpathid : & mut isize ,
202
- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
225
+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
203
226
) {
204
227
if let Some ( generics) = & mut ty. generics {
205
228
for item in generics {
@@ -296,7 +319,7 @@ pub(crate) fn build_index<'tcx>(
296
319
}
297
320
}
298
321
299
- let Cache { ref paths, .. } = * cache;
322
+ let Cache { ref paths, ref exact_paths , ref external_paths , .. } = * cache;
300
323
301
324
// Then, on parent modules
302
325
let crate_items: Vec < & IndexItem > = search_index
@@ -311,14 +334,56 @@ pub(crate) fn build_index<'tcx>(
311
334
lastpathid += 1 ;
312
335
313
336
if let Some ( & ( ref fqp, short) ) = paths. get ( & defid) {
314
- crate_paths. push ( ( short, fqp. clone ( ) ) ) ;
337
+ let exact_fqp = exact_paths
338
+ . get ( & defid)
339
+ . or_else ( || external_paths. get ( & defid) . map ( |& ( ref fqp, _) | fqp) )
340
+ . filter ( |exact_fqp| {
341
+ exact_fqp. last ( ) == Some ( & item. name ) && * exact_fqp != fqp
342
+ } ) ;
343
+ crate_paths. push ( ( short, fqp. clone ( ) , exact_fqp. cloned ( ) ) ) ;
315
344
Some ( pathid)
316
345
} else {
317
346
None
318
347
}
319
348
}
320
349
} ) ;
321
350
351
+ if let Some ( defid) = item. defid
352
+ && item. parent_idx . is_none ( )
353
+ {
354
+ // If this is a re-export, retain the original path.
355
+ // Associated items don't use this.
356
+ // Their parent carries the exact fqp instead.
357
+ let exact_fqp = exact_paths
358
+ . get ( & defid)
359
+ . or_else ( || external_paths. get ( & defid) . map ( |& ( ref fqp, _) | fqp) ) ;
360
+ item. exact_path = exact_fqp. and_then ( |fqp| {
361
+ // Re-exports only count if the name is exactly the same.
362
+ // This is a size optimization, since it means we only need
363
+ // to store the name once (and the path is re-used for everything
364
+ // exported from this same module). It's also likely to Do
365
+ // What I Mean, since if a re-export changes the name, it might
366
+ // also be a change in semantic meaning.
367
+ if fqp. last ( ) != Some ( & item. name ) {
368
+ return None ;
369
+ }
370
+ let path =
371
+ if item. ty == ItemType :: Macro && tcx. has_attr ( defid, sym:: macro_export) {
372
+ // `#[macro_export]` always exports to the crate root.
373
+ tcx. crate_name ( defid. krate ) . to_string ( )
374
+ } else {
375
+ if fqp. len ( ) < 2 {
376
+ return None ;
377
+ }
378
+ join_with_double_colon ( & fqp[ ..fqp. len ( ) - 1 ] )
379
+ } ;
380
+ if path == item. path {
381
+ return None ;
382
+ }
383
+ Some ( path)
384
+ } ) ;
385
+ }
386
+
322
387
// Omit the parent path if it is same to that of the prior item.
323
388
if lastpath == & item. path {
324
389
item. path . clear ( ) ;
@@ -356,7 +421,7 @@ pub(crate) fn build_index<'tcx>(
356
421
357
422
struct CrateData < ' a > {
358
423
items : Vec < & ' a IndexItem > ,
359
- paths : Vec < ( ItemType , Vec < Symbol > ) > ,
424
+ paths : Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
360
425
// The String is alias name and the vec is the list of the elements with this alias.
361
426
//
362
427
// To be noted: the `usize` elements are indexes to `items`.
@@ -374,6 +439,7 @@ pub(crate) fn build_index<'tcx>(
374
439
ty : ItemType ,
375
440
name : Symbol ,
376
441
path : Option < usize > ,
442
+ exact_path : Option < usize > ,
377
443
}
378
444
379
445
impl Serialize for Paths {
@@ -387,6 +453,10 @@ pub(crate) fn build_index<'tcx>(
387
453
if let Some ( ref path) = self . path {
388
454
seq. serialize_element ( path) ?;
389
455
}
456
+ if let Some ( ref path) = self . exact_path {
457
+ assert ! ( self . path. is_some( ) ) ;
458
+ seq. serialize_element ( path) ?;
459
+ }
390
460
seq. end ( )
391
461
}
392
462
}
@@ -409,43 +479,94 @@ pub(crate) fn build_index<'tcx>(
409
479
mod_paths. insert ( & item. path , index) ;
410
480
}
411
481
let mut paths = Vec :: with_capacity ( self . paths . len ( ) ) ;
412
- for ( ty, path) in & self . paths {
482
+ for ( ty, path, exact ) in & self . paths {
413
483
if path. len ( ) < 2 {
414
- paths. push ( Paths { ty : * ty, name : path[ 0 ] , path : None } ) ;
484
+ paths. push ( Paths { ty : * ty, name : path[ 0 ] , path : None , exact_path : None } ) ;
415
485
continue ;
416
486
}
417
487
let full_path = join_with_double_colon ( & path[ ..path. len ( ) - 1 ] ) ;
488
+ let full_exact_path = exact
489
+ . as_ref ( )
490
+ . filter ( |exact| exact. last ( ) == path. last ( ) && exact. len ( ) >= 2 )
491
+ . map ( |exact| join_with_double_colon ( & exact[ ..exact. len ( ) - 1 ] ) ) ;
492
+ let exact_path = extra_paths. len ( ) + self . items . len ( ) ;
493
+ let exact_path = full_exact_path. as_ref ( ) . map ( |full_exact_path| match extra_paths
494
+ . entry ( full_exact_path. clone ( ) )
495
+ {
496
+ Entry :: Occupied ( entry) => * entry. get ( ) ,
497
+ Entry :: Vacant ( entry) => {
498
+ if let Some ( index) = mod_paths. get ( & full_exact_path) {
499
+ return * index;
500
+ }
501
+ entry. insert ( exact_path) ;
502
+ if !revert_extra_paths. contains_key ( & exact_path) {
503
+ revert_extra_paths. insert ( exact_path, full_exact_path. clone ( ) ) ;
504
+ }
505
+ exact_path
506
+ }
507
+ } ) ;
418
508
if let Some ( index) = mod_paths. get ( & full_path) {
419
- paths. push ( Paths { ty : * ty, name : * path. last ( ) . unwrap ( ) , path : Some ( * index) } ) ;
509
+ paths. push ( Paths {
510
+ ty : * ty,
511
+ name : * path. last ( ) . unwrap ( ) ,
512
+ path : Some ( * index) ,
513
+ exact_path,
514
+ } ) ;
420
515
continue ;
421
516
}
422
517
// It means it comes from an external crate so the item and its path will be
423
518
// stored into another array.
424
519
//
425
520
// `index` is put after the last `mod_paths`
426
521
let index = extra_paths. len ( ) + self . items . len ( ) ;
427
- if !revert_extra_paths. contains_key ( & index) {
428
- revert_extra_paths. insert ( index, full_path. clone ( ) ) ;
429
- }
430
- match extra_paths. entry ( full_path) {
522
+ match extra_paths. entry ( full_path. clone ( ) ) {
431
523
Entry :: Occupied ( entry) => {
432
524
paths. push ( Paths {
433
525
ty : * ty,
434
526
name : * path. last ( ) . unwrap ( ) ,
435
527
path : Some ( * entry. get ( ) ) ,
528
+ exact_path,
436
529
} ) ;
437
530
}
438
531
Entry :: Vacant ( entry) => {
439
532
entry. insert ( index) ;
533
+ if !revert_extra_paths. contains_key ( & index) {
534
+ revert_extra_paths. insert ( index, full_path) ;
535
+ }
440
536
paths. push ( Paths {
441
537
ty : * ty,
442
538
name : * path. last ( ) . unwrap ( ) ,
443
539
path : Some ( index) ,
540
+ exact_path,
444
541
} ) ;
445
542
}
446
543
}
447
544
}
448
545
546
+ // Direct exports use adjacent arrays for the current crate's items,
547
+ // but re-exported exact paths don't.
548
+ let mut re_exports = Vec :: new ( ) ;
549
+ for ( item_index, item) in self . items . iter ( ) . enumerate ( ) {
550
+ if let Some ( exact_path) = item. exact_path . as_ref ( ) {
551
+ if let Some ( path_index) = mod_paths. get ( & exact_path) {
552
+ re_exports. push ( ( item_index, * path_index) ) ;
553
+ } else {
554
+ let path_index = extra_paths. len ( ) + self . items . len ( ) ;
555
+ let path_index = match extra_paths. entry ( exact_path. clone ( ) ) {
556
+ Entry :: Occupied ( entry) => * entry. get ( ) ,
557
+ Entry :: Vacant ( entry) => {
558
+ entry. insert ( path_index) ;
559
+ if !revert_extra_paths. contains_key ( & path_index) {
560
+ revert_extra_paths. insert ( path_index, exact_path. clone ( ) ) ;
561
+ }
562
+ path_index
563
+ }
564
+ } ;
565
+ re_exports. push ( ( item_index, path_index) ) ;
566
+ }
567
+ }
568
+ }
569
+
449
570
let mut names = Vec :: with_capacity ( self . items . len ( ) ) ;
450
571
let mut types = String :: with_capacity ( self . items . len ( ) ) ;
451
572
let mut full_paths = Vec :: with_capacity ( self . items . len ( ) ) ;
@@ -501,6 +622,7 @@ pub(crate) fn build_index<'tcx>(
501
622
crate_data. serialize_field ( "f" , & functions) ?;
502
623
crate_data. serialize_field ( "D" , & self . desc_index ) ?;
503
624
crate_data. serialize_field ( "p" , & paths) ?;
625
+ crate_data. serialize_field ( "r" , & re_exports) ?;
504
626
crate_data. serialize_field ( "b" , & self . associated_item_disambiguators ) ?;
505
627
crate_data. serialize_field ( "c" , & bitmap_to_string ( & deprecated) ) ?;
506
628
crate_data. serialize_field ( "e" , & bitmap_to_string ( & self . empty_desc ) ) ?;
0 commit comments