@@ -133,8 +133,8 @@ provide! { <'tcx> tcx, def_id, other, cdata,
133133 generator_kind => { cdata. generator_kind( def_id. index) }
134134 opt_def_kind => { Some ( cdata. def_kind( def_id. index) ) }
135135 def_span => { cdata. get_span( def_id. index, & tcx. sess) }
136- def_ident_span => {
137- cdata. try_item_ident( def_id. index, & tcx. sess) . ok( ) . map ( |ident| ident . span )
136+ def_ident => {
137+ cdata. try_item_ident( def_id. index, & tcx. sess) . ok( )
138138 }
139139 lookup_stability => {
140140 cdata. get_stability( def_id. index) . map( |s| tcx. intern_stability( s) )
@@ -290,15 +290,11 @@ pub fn provide(providers: &mut Providers) {
290290 // external item that is visible from at least one local module) to a
291291 // sufficiently visible parent (considering modules that re-export the
292292 // external item to be parents).
293- visible_parent_map : |tcx, ( ) | {
294- use std :: collections :: hash_map :: Entry ;
295- use std:: collections:: vec_deque :: VecDeque ;
293+ visible_parents_map : |tcx, ( ) | {
294+ use rustc_data_structures :: fx :: FxHashSet ;
295+ use std:: collections:: VecDeque ;
296296
297- let mut visible_parent_map: DefIdMap < DefId > = Default :: default ( ) ;
298- // This is a secondary visible_parent_map, storing the DefId of parents that re-export
299- // the child as `_`. Since we prefer parents that don't do this, merge this map at the
300- // end, only if we're missing any keys from the former.
301- let mut fallback_map: DefIdMap < DefId > = Default :: default ( ) ;
297+ let mut visible_parents_map: DefIdMap < SmallVec < [ DefId ; 4 ] > > = DefIdMap :: default ( ) ;
302298
303299 // Issue 46112: We want the map to prefer the shortest
304300 // paths when reporting the path to an item. Therefore we
@@ -310,59 +306,81 @@ pub fn provide(providers: &mut Providers) {
310306 // only get paths that are locally minimal with respect to
311307 // whatever crate we happened to encounter first in this
312308 // traversal, but not globally minimal across all crates.
313- let bfs_queue = & mut VecDeque :: new ( ) ;
314-
315- for & cnum in tcx. crates ( ( ) ) {
316- // Ignore crates without a corresponding local `extern crate` item.
317- if tcx. missing_extern_crate_item ( cnum) {
318- continue ;
309+ let mut bfs_queue = VecDeque :: default ( ) ;
310+
311+ bfs_queue. extend (
312+ tcx. crates ( ( ) )
313+ . into_iter ( )
314+ // Ignore crates without a corresponding local `extern crate` item.
315+ . filter ( |cnum| !tcx. missing_extern_crate_item ( * * cnum) )
316+ . map ( |cnum| DefId { krate : * cnum, index : CRATE_DEF_INDEX } ) ,
317+ ) ;
318+
319+ // Iterate over graph using BFS.
320+ // Filter out any non-public items.
321+ while let Some ( parent) = bfs_queue. pop_front ( ) {
322+ for child in tcx
323+ . item_children ( parent)
324+ . iter ( )
325+ . filter ( |child| child. vis . is_public ( ) )
326+ . filter_map ( |child| child. res . opt_def_id ( ) )
327+ {
328+ visible_parents_map
329+ . entry ( child)
330+ . or_insert_with ( || {
331+ // If we encounter node the first time
332+ // add it to queue for next iterations
333+ bfs_queue. push_back ( child) ;
334+ Default :: default ( )
335+ } )
336+ . push ( parent) ;
319337 }
338+ }
320339
321- bfs_queue. push_back ( DefId { krate : cnum, index : CRATE_DEF_INDEX } ) ;
340+ // Iterate over parents vector to remove duplicate elements
341+ // while preserving order
342+ let mut dedup_set = FxHashSet :: default ( ) ;
343+ for ( _, parents) in & mut visible_parents_map {
344+ parents. retain ( |parent| dedup_set. insert ( * parent) ) ;
345+
346+ // Reuse hashset allocation.
347+ dedup_set. clear ( ) ;
322348 }
323349
324- let mut add_child = |bfs_queue : & mut VecDeque < _ > , export : & Export , parent : DefId | {
325- if !export. vis . is_public ( ) {
326- return ;
327- }
350+ visible_parents_map
351+ } ,
352+ best_visible_parent : |tcx, child| {
353+ // Use `min_by_key` because it returns
354+ // first match in case keys are equal
355+ tcx. visible_parents_map ( ( ) )
356+ . get ( & child) ?
357+ . into_iter ( )
358+ . min_by_key ( |parent| {
359+ // If this is just regular export in another module, assign it a neutral score.
360+ let mut score = 0 ;
361+
362+ // If child and parent are local, we prefer them
363+ if child. is_local ( ) && parent. is_local ( ) {
364+ score += 1 ;
365+ }
328366
329- if let Some ( child) = export . res . opt_def_id ( ) {
330- if export . ident . name == kw :: Underscore {
331- fallback_map . insert ( child , parent) ;
332- return ;
367+ // Even if child and parent are local, if parent is `#[doc(hidden)]`
368+ // We reduce their score to avoid showing items not popping in documentation.
369+ if ast :: attr :: is_doc_hidden ( tcx . item_attrs ( * * parent) ) {
370+ score -= 2 ;
333371 }
334372
335- match visible_parent_map. entry ( child) {
336- Entry :: Occupied ( mut entry) => {
337- // If `child` is defined in crate `cnum`, ensure
338- // that it is mapped to a parent in `cnum`.
339- if child. is_local ( ) && entry. get ( ) . is_local ( ) {
340- entry. insert ( parent) ;
341- }
342- }
343- Entry :: Vacant ( entry) => {
344- entry. insert ( parent) ;
345- bfs_queue. push_back ( child) ;
373+ // If parent identifier is _ we prefer it only as last resort if other items are not available
374+ if let Some ( ident) = tcx. def_ident ( * * parent) {
375+ if ident. name == kw:: Underscore {
376+ score -= 3 ;
346377 }
347378 }
348- }
349- } ;
350-
351- while let Some ( def) = bfs_queue. pop_front ( ) {
352- for child in tcx. item_children ( def) . iter ( ) {
353- add_child ( bfs_queue, child, def) ;
354- }
355- }
356379
357- // Fill in any missing entries with the (less preferable) path ending in `::_`.
358- // We still use this path in a diagnostic that suggests importing `::*`.
359- for ( child, parent) in fallback_map {
360- visible_parent_map. entry ( child) . or_insert ( parent) ;
361- }
362-
363- visible_parent_map
380+ -score
381+ } )
382+ . map ( ToOwned :: to_owned)
364383 } ,
365-
366384 dependency_formats : |tcx, ( ) | Lrc :: new ( crate :: dependency_format:: calculate ( tcx) ) ,
367385 has_global_allocator : |tcx, cnum| {
368386 assert_eq ! ( cnum, LOCAL_CRATE ) ;
0 commit comments