@@ -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,30 @@ 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, as well as a DWIM attempt
175
+ // since if the names are not the same, the intent probably
176
+ // isn't, either
177
+ . filter ( |fqp| fqp. last ( ) == fqp. last ( ) ) ;
160
178
Some ( insert_into_map (
161
179
itemid_to_pathid,
162
180
ItemId :: DefId ( defid) ,
163
181
lastpathid,
164
182
crate_paths,
165
183
item_type,
166
184
fqp,
185
+ exact_fqp. map ( |x| & x[ ..] ) . filter ( |exact_fqp| exact_fqp != fqp) ,
167
186
) )
168
187
} else {
169
188
None
@@ -178,6 +197,7 @@ pub(crate) fn build_index<'tcx>(
178
197
crate_paths,
179
198
ItemType :: Primitive ,
180
199
& [ sym] ,
200
+ None ,
181
201
) )
182
202
}
183
203
RenderTypeId :: Index ( _) => Some ( id) ,
@@ -188,6 +208,7 @@ pub(crate) fn build_index<'tcx>(
188
208
crate_paths,
189
209
ItemType :: AssocType ,
190
210
& [ sym] ,
211
+ None ,
191
212
) ) ,
192
213
}
193
214
}
@@ -199,7 +220,7 @@ pub(crate) fn build_index<'tcx>(
199
220
primitives : & mut FxHashMap < Symbol , isize > ,
200
221
associated_types : & mut FxHashMap < Symbol , isize > ,
201
222
lastpathid : & mut isize ,
202
- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
223
+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
203
224
) {
204
225
if let Some ( generics) = & mut ty. generics {
205
226
for item in generics {
@@ -296,7 +317,7 @@ pub(crate) fn build_index<'tcx>(
296
317
}
297
318
}
298
319
299
- let Cache { ref paths, .. } = * cache;
320
+ let Cache { ref paths, ref exact_paths , ref external_paths , .. } = * cache;
300
321
301
322
// Then, on parent modules
302
323
let crate_items: Vec < & IndexItem > = search_index
@@ -311,14 +332,54 @@ pub(crate) fn build_index<'tcx>(
311
332
lastpathid += 1 ;
312
333
313
334
if let Some ( & ( ref fqp, short) ) = paths. get ( & defid) {
314
- crate_paths. push ( ( short, fqp. clone ( ) ) ) ;
335
+ let exact_fqp = exact_paths
336
+ . get ( & defid)
337
+ . or_else ( || external_paths. get ( & defid) . map ( |& ( ref fqp, _) | fqp) )
338
+ . filter ( |exact_fqp| {
339
+ exact_fqp. last ( ) == Some ( & item. name ) && * exact_fqp != fqp
340
+ } ) ;
341
+ crate_paths. push ( ( short, fqp. clone ( ) , exact_fqp. cloned ( ) ) ) ;
315
342
Some ( pathid)
316
343
} else {
317
344
None
318
345
}
319
346
}
320
347
} ) ;
321
348
349
+ if let Some ( defid) = item. defid
350
+ && item. parent_idx . is_none ( )
351
+ {
352
+ // If this is a re-export, retain the original path.
353
+ // Associated items don't use this.
354
+ // Their parent carries the exact fqp instead.
355
+ let exact_fqp = exact_paths
356
+ . get ( & defid)
357
+ . or_else ( || external_paths. get ( & defid) . map ( |& ( ref fqp, _) | fqp) ) ;
358
+ item. exact_path = exact_fqp. and_then ( |fqp| {
359
+ // re-exports only count if the name is exactly the same
360
+ // this is a size optimization, as well as a DWIM attempt
361
+ // since if the names are not the same, the intent probably
362
+ // isn't, either
363
+ if fqp. last ( ) != Some ( & item. name ) {
364
+ return None ;
365
+ }
366
+ let path =
367
+ if item. ty == ItemType :: Macro && tcx. has_attr ( defid, sym:: macro_export) {
368
+ // `#[macro_export]` always exports to the crate root.
369
+ tcx. crate_name ( defid. krate ) . to_string ( )
370
+ } else {
371
+ if fqp. len ( ) < 2 {
372
+ return None ;
373
+ }
374
+ join_with_double_colon ( & fqp[ ..fqp. len ( ) - 1 ] )
375
+ } ;
376
+ if path == item. path {
377
+ return None ;
378
+ }
379
+ Some ( path)
380
+ } ) ;
381
+ }
382
+
322
383
// Omit the parent path if it is same to that of the prior item.
323
384
if lastpath == & item. path {
324
385
item. path . clear ( ) ;
@@ -356,7 +417,7 @@ pub(crate) fn build_index<'tcx>(
356
417
357
418
struct CrateData < ' a > {
358
419
items : Vec < & ' a IndexItem > ,
359
- paths : Vec < ( ItemType , Vec < Symbol > ) > ,
420
+ paths : Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
360
421
// The String is alias name and the vec is the list of the elements with this alias.
361
422
//
362
423
// To be noted: the `usize` elements are indexes to `items`.
@@ -374,6 +435,7 @@ pub(crate) fn build_index<'tcx>(
374
435
ty : ItemType ,
375
436
name : Symbol ,
376
437
path : Option < usize > ,
438
+ exact_path : Option < usize > ,
377
439
}
378
440
379
441
impl Serialize for Paths {
@@ -387,6 +449,10 @@ pub(crate) fn build_index<'tcx>(
387
449
if let Some ( ref path) = self . path {
388
450
seq. serialize_element ( path) ?;
389
451
}
452
+ if let Some ( ref path) = self . exact_path {
453
+ assert ! ( self . path. is_some( ) ) ;
454
+ seq. serialize_element ( path) ?;
455
+ }
390
456
seq. end ( )
391
457
}
392
458
}
@@ -409,43 +475,94 @@ pub(crate) fn build_index<'tcx>(
409
475
mod_paths. insert ( & item. path , index) ;
410
476
}
411
477
let mut paths = Vec :: with_capacity ( self . paths . len ( ) ) ;
412
- for ( ty, path) in & self . paths {
478
+ for ( ty, path, exact ) in & self . paths {
413
479
if path. len ( ) < 2 {
414
- paths. push ( Paths { ty : * ty, name : path[ 0 ] , path : None } ) ;
480
+ paths. push ( Paths { ty : * ty, name : path[ 0 ] , path : None , exact_path : None } ) ;
415
481
continue ;
416
482
}
417
483
let full_path = join_with_double_colon ( & path[ ..path. len ( ) - 1 ] ) ;
484
+ let full_exact_path = exact
485
+ . as_ref ( )
486
+ . filter ( |exact| exact. last ( ) == path. last ( ) && exact. len ( ) >= 2 )
487
+ . map ( |exact| join_with_double_colon ( & exact[ ..exact. len ( ) - 1 ] ) ) ;
488
+ let exact_path = extra_paths. len ( ) + self . items . len ( ) ;
489
+ let exact_path = full_exact_path. as_ref ( ) . map ( |full_exact_path| match extra_paths
490
+ . entry ( full_exact_path. clone ( ) )
491
+ {
492
+ Entry :: Occupied ( entry) => * entry. get ( ) ,
493
+ Entry :: Vacant ( entry) => {
494
+ if let Some ( index) = mod_paths. get ( & full_exact_path) {
495
+ return * index;
496
+ }
497
+ entry. insert ( exact_path) ;
498
+ if !revert_extra_paths. contains_key ( & exact_path) {
499
+ revert_extra_paths. insert ( exact_path, full_exact_path. clone ( ) ) ;
500
+ }
501
+ exact_path
502
+ }
503
+ } ) ;
418
504
if let Some ( index) = mod_paths. get ( & full_path) {
419
- paths. push ( Paths { ty : * ty, name : * path. last ( ) . unwrap ( ) , path : Some ( * index) } ) ;
505
+ paths. push ( Paths {
506
+ ty : * ty,
507
+ name : * path. last ( ) . unwrap ( ) ,
508
+ path : Some ( * index) ,
509
+ exact_path,
510
+ } ) ;
420
511
continue ;
421
512
}
422
513
// It means it comes from an external crate so the item and its path will be
423
514
// stored into another array.
424
515
//
425
516
// `index` is put after the last `mod_paths`
426
517
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) {
518
+ match extra_paths. entry ( full_path. clone ( ) ) {
431
519
Entry :: Occupied ( entry) => {
432
520
paths. push ( Paths {
433
521
ty : * ty,
434
522
name : * path. last ( ) . unwrap ( ) ,
435
523
path : Some ( * entry. get ( ) ) ,
524
+ exact_path,
436
525
} ) ;
437
526
}
438
527
Entry :: Vacant ( entry) => {
439
528
entry. insert ( index) ;
529
+ if !revert_extra_paths. contains_key ( & index) {
530
+ revert_extra_paths. insert ( index, full_path) ;
531
+ }
440
532
paths. push ( Paths {
441
533
ty : * ty,
442
534
name : * path. last ( ) . unwrap ( ) ,
443
535
path : Some ( index) ,
536
+ exact_path,
444
537
} ) ;
445
538
}
446
539
}
447
540
}
448
541
542
+ // Direct exports use adjacent arrays for the current crate's items,
543
+ // but re-exported exact paths don't.
544
+ let mut re_exports = Vec :: new ( ) ;
545
+ for ( item_index, item) in self . items . iter ( ) . enumerate ( ) {
546
+ if let Some ( exact_path) = item. exact_path . as_ref ( ) {
547
+ if let Some ( path_index) = mod_paths. get ( & exact_path) {
548
+ re_exports. push ( ( item_index, * path_index) ) ;
549
+ } else {
550
+ let path_index = extra_paths. len ( ) + self . items . len ( ) ;
551
+ let path_index = match extra_paths. entry ( exact_path. clone ( ) ) {
552
+ Entry :: Occupied ( entry) => * entry. get ( ) ,
553
+ Entry :: Vacant ( entry) => {
554
+ entry. insert ( path_index) ;
555
+ if !revert_extra_paths. contains_key ( & path_index) {
556
+ revert_extra_paths. insert ( path_index, exact_path. clone ( ) ) ;
557
+ }
558
+ path_index
559
+ }
560
+ } ;
561
+ re_exports. push ( ( item_index, path_index) ) ;
562
+ }
563
+ }
564
+ }
565
+
449
566
let mut names = Vec :: with_capacity ( self . items . len ( ) ) ;
450
567
let mut types = String :: with_capacity ( self . items . len ( ) ) ;
451
568
let mut full_paths = Vec :: with_capacity ( self . items . len ( ) ) ;
@@ -501,6 +618,7 @@ pub(crate) fn build_index<'tcx>(
501
618
crate_data. serialize_field ( "f" , & functions) ?;
502
619
crate_data. serialize_field ( "D" , & self . desc_index ) ?;
503
620
crate_data. serialize_field ( "p" , & paths) ?;
621
+ crate_data. serialize_field ( "r" , & re_exports) ?;
504
622
crate_data. serialize_field ( "b" , & self . associated_item_disambiguators ) ?;
505
623
crate_data. serialize_field ( "c" , & bitmap_to_string ( & deprecated) ) ?;
506
624
crate_data. serialize_field ( "e" , & bitmap_to_string ( & self . empty_desc ) ) ?;
0 commit comments