1
1
use crate :: creader:: { CStore , LoadedMacro } ;
2
2
use crate :: foreign_modules;
3
3
use crate :: native_libs;
4
+ use crate :: rmeta:: ty:: util:: is_doc_hidden;
4
5
5
6
use rustc_ast as ast;
6
7
use rustc_attr:: Deprecation ;
7
- use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
8
+ use rustc_hir:: def:: { CtorKind , DefKind } ;
8
9
use rustc_hir:: def_id:: { CrateNum , DefId , DefIdMap , LOCAL_CRATE } ;
9
10
use rustc_hir:: definitions:: { DefKey , DefPath , DefPathHash } ;
10
11
use rustc_middle:: arena:: ArenaAllocatable ;
@@ -367,15 +368,15 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
367
368
// external item that is visible from at least one local module) to a
368
369
// sufficiently visible parent (considering modules that re-export the
369
370
// external item to be parents).
370
- visible_parent_map : |tcx, ( ) | {
371
- use std:: collections:: hash_map:: Entry ;
372
- use std:: collections:: vec_deque:: VecDeque ;
371
+ // Returns a map from a sufficiently visible external item (i.e., an
372
+ // external item that is visible from at least one local module) to a
373
+ // sufficiently visible parent (considering modules that re-export the
374
+ // external item to be parents).
375
+ visible_parents_map : |tcx, ( ) | {
376
+ use rustc_data_structures:: fx:: FxHashSet ;
377
+ use std:: collections:: VecDeque ;
373
378
374
- let mut visible_parent_map: DefIdMap < DefId > = Default :: default ( ) ;
375
- // This is a secondary visible_parent_map, storing the DefId of parents that re-export
376
- // the child as `_`. Since we prefer parents that don't do this, merge this map at the
377
- // end, only if we're missing any keys from the former.
378
- let mut fallback_map: DefIdMap < DefId > = Default :: default ( ) ;
379
+ let mut visible_parents_map: DefIdMap < SmallVec < [ _ ; 4 ] > > = DefIdMap :: default ( ) ;
379
380
380
381
// Issue 46112: We want the map to prefer the shortest
381
382
// paths when reporting the path to an item. Therefore we
@@ -387,62 +388,88 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
387
388
// only get paths that are locally minimal with respect to
388
389
// whatever crate we happened to encounter first in this
389
390
// traversal, but not globally minimal across all crates.
390
- let bfs_queue = & mut VecDeque :: new ( ) ;
391
-
392
- for & cnum in tcx. crates ( ( ) ) {
393
- // Ignore crates without a corresponding local `extern crate` item.
394
- if tcx. missing_extern_crate_item ( cnum) {
395
- continue ;
391
+ let mut bfs_queue = VecDeque :: default ( ) ;
392
+
393
+ bfs_queue. extend (
394
+ tcx. crates ( ( ) )
395
+ . into_iter ( )
396
+ // Ignore crates without a corresponding local `extern crate` item.
397
+ . filter ( |cnum| !tcx. missing_extern_crate_item ( * * cnum) )
398
+ . map ( |cnum| DefId { krate : * cnum, index : super :: CRATE_DEF_INDEX } ) ,
399
+ ) ;
400
+
401
+ // Iterate over graph using BFS.
402
+ // Filter out any non-public items.
403
+ while let Some ( parent) = bfs_queue. pop_front ( ) {
404
+ if matches ! ( tcx. def_kind( parent) , DefKind :: Mod | DefKind :: Enum | DefKind :: Trait ) {
405
+ for ( child_def_id, child_name) in tcx
406
+ . module_children ( parent)
407
+ . iter ( )
408
+ . filter ( |child| child. vis . is_public ( ) )
409
+ . filter_map ( |child| Some ( ( child. res . opt_def_id ( ) ?, child. ident . name ) ) )
410
+ {
411
+ visible_parents_map
412
+ . entry ( child_def_id)
413
+ . or_insert_with ( || {
414
+ // If we encounter node the first time
415
+ // add it to queue for next iterations
416
+ bfs_queue. push_back ( child_def_id) ;
417
+ Default :: default ( )
418
+ } )
419
+ . push ( ( parent, child_name) ) ;
420
+ }
396
421
}
397
-
398
- bfs_queue. push_back ( cnum. as_def_id ( ) ) ;
399
422
}
400
423
401
- let mut add_child = |bfs_queue : & mut VecDeque < _ > , child : & ModChild , parent : DefId | {
402
- if !child. vis . is_public ( ) {
403
- return ;
404
- }
424
+ // Iterate over parents vector to remove duplicate elements
425
+ // while preserving order
426
+ let mut dedup_set = FxHashSet :: default ( ) ;
427
+ for ( _, parents) in & mut visible_parents_map {
428
+ parents. retain ( |parent| dedup_set. insert ( * parent) ) ;
429
+
430
+ // Reuse hashset allocation.
431
+ dedup_set. clear ( ) ;
432
+ }
405
433
406
- if let Some ( def_id) = child. res . opt_def_id ( ) {
407
- if child. ident . name == kw:: Underscore {
408
- fallback_map. insert ( def_id, parent) ;
409
- return ;
434
+ visible_parents_map
435
+ } ,
436
+ best_visible_parent : |tcx, child| {
437
+ // Use `min_by_key` because it returns
438
+ // first match in case keys are equal
439
+ tcx. visible_parents_map ( ( ) )
440
+ . get ( & child) ?
441
+ . into_iter ( )
442
+ . min_by_key ( |( parent, child_name) | {
443
+ // If this is just regular export in another module, assign it a neutral score.
444
+ let mut score = 0 ;
445
+
446
+ // If child and parent are local, we prefer them
447
+ if child. is_local ( ) && parent. is_local ( ) {
448
+ score += 1 ;
410
449
}
411
450
412
- match visible_parent_map. entry ( def_id) {
413
- Entry :: Occupied ( mut entry) => {
414
- // If `child` is defined in crate `cnum`, ensure
415
- // that it is mapped to a parent in `cnum`.
416
- if def_id. is_local ( ) && entry. get ( ) . is_local ( ) {
417
- entry. insert ( parent) ;
418
- }
419
- }
420
- Entry :: Vacant ( entry) => {
421
- entry. insert ( parent) ;
422
- if matches ! (
423
- child. res,
424
- Res :: Def ( DefKind :: Mod | DefKind :: Enum | DefKind :: Trait , _)
425
- ) {
426
- bfs_queue. push_back ( def_id) ;
427
- }
428
- }
451
+ // Even if child and parent are local, if parent is `#[doc(hidden)]`
452
+ // We reduce their score to avoid showing items not popping in documentation.
453
+ if is_doc_hidden ( tcx, * parent) {
454
+ score -= 2 ;
429
455
}
430
- }
431
- } ;
432
456
433
- while let Some ( def) = bfs_queue. pop_front ( ) {
434
- for child in tcx. module_children ( def) . iter ( ) {
435
- add_child ( bfs_queue, child, def) ;
436
- }
437
- }
457
+ // If parent identifier is _ we prefer it only as last resort if other items are not available
458
+ if let Some ( name) = tcx. opt_item_name ( * parent)
459
+ && name == kw:: Underscore
460
+ {
461
+ score -= 3 ;
462
+ }
438
463
439
- // Fill in any missing entries with the (less preferable) path ending in `::_`.
440
- // We still use this path in a diagnostic that suggests importing `::*` .
441
- for ( child , parent ) in fallback_map {
442
- visible_parent_map . entry ( child ) . or_insert ( parent ) ;
443
- }
464
+ // If the name of the child inside of the parent (i.e. its re-exported name),
465
+ // then also don't prefer that.. .
466
+ if * child_name == kw :: Underscore {
467
+ score -= 3 ;
468
+ }
444
469
445
- visible_parent_map
470
+ -score
471
+ } )
472
+ . map ( |( parent, _) | * parent)
446
473
} ,
447
474
448
475
dependency_formats : |tcx, ( ) | Lrc :: new ( crate :: dependency_format:: calculate ( tcx) ) ,
0 commit comments