@@ -59,10 +59,13 @@ pub(crate) fn build_index<'tcx>(
5959 cache : & mut Cache ,
6060 tcx : TyCtxt < ' tcx > ,
6161) -> SerializedSearchIndex {
62+ // Maps from ID to position in the `crate_paths` array.
6263 let mut itemid_to_pathid = FxHashMap :: default ( ) ;
6364 let mut primitives = FxHashMap :: default ( ) ;
6465 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 ! [ ] ;
6669
6770 // Attach all orphan items to the type's definition if the type
6871 // has since been learned.
@@ -72,11 +75,13 @@ pub(crate) fn build_index<'tcx>(
7275 let desc = short_markdown_summary ( & item. doc_value ( ) , & item. link_names ( cache) ) ;
7376 cache. search_index . push ( IndexItem {
7477 ty : item. type_ ( ) ,
78+ defid : item. item_id . as_def_id ( ) ,
7579 name : item. name . unwrap ( ) ,
7680 path : join_with_double_colon ( & fqp[ ..fqp. len ( ) - 1 ] ) ,
7781 desc,
7882 parent : Some ( parent) ,
7983 parent_idx : None ,
84+ exact_path : None ,
8085 impl_id,
8186 search_type : get_function_type_for_search (
8287 item,
@@ -126,17 +131,22 @@ pub(crate) fn build_index<'tcx>(
126131 map : & mut FxHashMap < F , isize > ,
127132 itemid : F ,
128133 lastpathid : & mut isize ,
129- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
134+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
130135 item_type : ItemType ,
131136 path : & [ Symbol ] ,
137+ exact_path : Option < & [ Symbol ] > ,
132138 ) -> RenderTypeId {
133139 match map. entry ( itemid) {
134140 Entry :: Occupied ( entry) => RenderTypeId :: Index ( * entry. get ( ) ) ,
135141 Entry :: Vacant ( entry) => {
136142 let pathid = * lastpathid;
137143 entry. insert ( pathid) ;
138144 * 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+ ) ) ;
140150 RenderTypeId :: Index ( pathid)
141151 }
142152 }
@@ -149,21 +159,30 @@ pub(crate) fn build_index<'tcx>(
149159 primitives : & mut FxHashMap < Symbol , isize > ,
150160 associated_types : & mut FxHashMap < Symbol , isize > ,
151161 lastpathid : & mut isize ,
152- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
162+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
153163 ) -> Option < RenderTypeId > {
154- let Cache { ref paths, ref external_paths, .. } = * cache;
164+ let Cache { ref paths, ref external_paths, ref exact_paths , .. } = * cache;
155165 match id {
156166 RenderTypeId :: DefId ( defid) => {
157167 if let Some ( & ( ref fqp, item_type) ) =
158168 paths. get ( & defid) . or_else ( || external_paths. get ( & defid) )
159169 {
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 ( ) ) ;
160178 Some ( insert_into_map (
161179 itemid_to_pathid,
162180 ItemId :: DefId ( defid) ,
163181 lastpathid,
164182 crate_paths,
165183 item_type,
166184 fqp,
185+ exact_fqp. map ( |x| & x[ ..] ) . filter ( |exact_fqp| exact_fqp != fqp) ,
167186 ) )
168187 } else {
169188 None
@@ -178,6 +197,7 @@ pub(crate) fn build_index<'tcx>(
178197 crate_paths,
179198 ItemType :: Primitive ,
180199 & [ sym] ,
200+ None ,
181201 ) )
182202 }
183203 RenderTypeId :: Index ( _) => Some ( id) ,
@@ -188,6 +208,7 @@ pub(crate) fn build_index<'tcx>(
188208 crate_paths,
189209 ItemType :: AssocType ,
190210 & [ sym] ,
211+ None ,
191212 ) ) ,
192213 }
193214 }
@@ -199,7 +220,7 @@ pub(crate) fn build_index<'tcx>(
199220 primitives : & mut FxHashMap < Symbol , isize > ,
200221 associated_types : & mut FxHashMap < Symbol , isize > ,
201222 lastpathid : & mut isize ,
202- crate_paths : & mut Vec < ( ItemType , Vec < Symbol > ) > ,
223+ crate_paths : & mut Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
203224 ) {
204225 if let Some ( generics) = & mut ty. generics {
205226 for item in generics {
@@ -296,7 +317,7 @@ pub(crate) fn build_index<'tcx>(
296317 }
297318 }
298319
299- let Cache { ref paths, .. } = * cache;
320+ let Cache { ref paths, ref exact_paths , ref external_paths , .. } = * cache;
300321
301322 // Then, on parent modules
302323 let crate_items: Vec < & IndexItem > = search_index
@@ -311,14 +332,54 @@ pub(crate) fn build_index<'tcx>(
311332 lastpathid += 1 ;
312333
313334 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 ( ) ) ) ;
315342 Some ( pathid)
316343 } else {
317344 None
318345 }
319346 }
320347 } ) ;
321348
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+
322383 // Omit the parent path if it is same to that of the prior item.
323384 if lastpath == & item. path {
324385 item. path . clear ( ) ;
@@ -356,7 +417,7 @@ pub(crate) fn build_index<'tcx>(
356417
357418 struct CrateData < ' a > {
358419 items : Vec < & ' a IndexItem > ,
359- paths : Vec < ( ItemType , Vec < Symbol > ) > ,
420+ paths : Vec < ( ItemType , Vec < Symbol > , Option < Vec < Symbol > > ) > ,
360421 // The String is alias name and the vec is the list of the elements with this alias.
361422 //
362423 // To be noted: the `usize` elements are indexes to `items`.
@@ -374,6 +435,7 @@ pub(crate) fn build_index<'tcx>(
374435 ty : ItemType ,
375436 name : Symbol ,
376437 path : Option < usize > ,
438+ exact_path : Option < usize > ,
377439 }
378440
379441 impl Serialize for Paths {
@@ -387,6 +449,10 @@ pub(crate) fn build_index<'tcx>(
387449 if let Some ( ref path) = self . path {
388450 seq. serialize_element ( path) ?;
389451 }
452+ if let Some ( ref path) = self . exact_path {
453+ assert ! ( self . path. is_some( ) ) ;
454+ seq. serialize_element ( path) ?;
455+ }
390456 seq. end ( )
391457 }
392458 }
@@ -409,43 +475,94 @@ pub(crate) fn build_index<'tcx>(
409475 mod_paths. insert ( & item. path , index) ;
410476 }
411477 let mut paths = Vec :: with_capacity ( self . paths . len ( ) ) ;
412- for ( ty, path) in & self . paths {
478+ for ( ty, path, exact ) in & self . paths {
413479 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 } ) ;
415481 continue ;
416482 }
417483 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+ } ) ;
418504 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+ } ) ;
420511 continue ;
421512 }
422513 // It means it comes from an external crate so the item and its path will be
423514 // stored into another array.
424515 //
425516 // `index` is put after the last `mod_paths`
426517 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 ( ) ) {
431519 Entry :: Occupied ( entry) => {
432520 paths. push ( Paths {
433521 ty : * ty,
434522 name : * path. last ( ) . unwrap ( ) ,
435523 path : Some ( * entry. get ( ) ) ,
524+ exact_path,
436525 } ) ;
437526 }
438527 Entry :: Vacant ( entry) => {
439528 entry. insert ( index) ;
529+ if !revert_extra_paths. contains_key ( & index) {
530+ revert_extra_paths. insert ( index, full_path) ;
531+ }
440532 paths. push ( Paths {
441533 ty : * ty,
442534 name : * path. last ( ) . unwrap ( ) ,
443535 path : Some ( index) ,
536+ exact_path,
444537 } ) ;
445538 }
446539 }
447540 }
448541
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+
449566 let mut names = Vec :: with_capacity ( self . items . len ( ) ) ;
450567 let mut types = String :: with_capacity ( self . items . len ( ) ) ;
451568 let mut full_paths = Vec :: with_capacity ( self . items . len ( ) ) ;
@@ -501,6 +618,7 @@ pub(crate) fn build_index<'tcx>(
501618 crate_data. serialize_field ( "f" , & functions) ?;
502619 crate_data. serialize_field ( "D" , & self . desc_index ) ?;
503620 crate_data. serialize_field ( "p" , & paths) ?;
621+ crate_data. serialize_field ( "r" , & re_exports) ?;
504622 crate_data. serialize_field ( "b" , & self . associated_item_disambiguators ) ?;
505623 crate_data. serialize_field ( "c" , & bitmap_to_string ( & deprecated) ) ?;
506624 crate_data. serialize_field ( "e" , & bitmap_to_string ( & self . empty_desc ) ) ?;
0 commit comments