@@ -98,6 +98,8 @@ pub(crate) struct ImportSuggestion {
9898 pub descr : & ' static str ,
9999 pub path : Path ,
100100 pub accessible : bool ,
101+ // false if the path traverses a foreign `#[doc(hidden)]` item.
102+ pub doc_visible : bool ,
101103 pub via_import : bool ,
102104 /// An extra note that should be issued if this item is suggested
103105 pub note : Option < String > ,
@@ -1153,10 +1155,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11531155 {
11541156 let mut candidates = Vec :: new ( ) ;
11551157 let mut seen_modules = FxHashSet :: default ( ) ;
1156- let mut worklist = vec ! [ ( start_module, ThinVec :: <ast:: PathSegment >:: new( ) , true ) ] ;
1158+ let start_did = start_module. def_id ( ) ;
1159+ let mut worklist = vec ! [ (
1160+ start_module,
1161+ ThinVec :: <ast:: PathSegment >:: new( ) ,
1162+ true ,
1163+ start_did. is_local( ) || !self . tcx. is_doc_hidden( start_did) ,
1164+ ) ] ;
11571165 let mut worklist_via_import = vec ! [ ] ;
11581166
1159- while let Some ( ( in_module, path_segments, accessible) ) = match worklist. pop ( ) {
1167+ while let Some ( ( in_module, path_segments, accessible, doc_visible ) ) = match worklist. pop ( ) {
11601168 None => worklist_via_import. pop ( ) ,
11611169 Some ( x) => Some ( x) ,
11621170 } {
@@ -1199,6 +1207,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11991207 }
12001208 }
12011209
1210+ let res = name_binding. res ( ) ;
1211+ let did = match res {
1212+ Res :: Def ( DefKind :: Ctor ( ..) , did) => this. tcx . opt_parent ( did) ,
1213+ _ => res. opt_def_id ( ) ,
1214+ } ;
1215+ let child_doc_visible = doc_visible
1216+ && ( did. map_or ( true , |did| did. is_local ( ) || !this. tcx . is_doc_hidden ( did) ) ) ;
1217+
12021218 // collect results based on the filter function
12031219 // avoid suggesting anything from the same module in which we are resolving
12041220 // avoid suggesting anything with a hygienic name
@@ -1207,7 +1223,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12071223 && in_module != parent_scope. module
12081224 && !ident. span . normalize_to_macros_2_0 ( ) . from_expansion ( )
12091225 {
1210- let res = name_binding. res ( ) ;
12111226 if filter_fn ( res) {
12121227 // create the path
12131228 let mut segms = if lookup_ident. span . at_least_rust_2018 ( ) {
@@ -1221,10 +1236,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12211236
12221237 segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
12231238 let path = Path { span : name_binding. span , segments : segms, tokens : None } ;
1224- let did = match res {
1225- Res :: Def ( DefKind :: Ctor ( ..) , did) => this. tcx . opt_parent ( did) ,
1226- _ => res. opt_def_id ( ) ,
1227- } ;
12281239
12291240 if child_accessible {
12301241 // Remove invisible match if exists
@@ -1264,6 +1275,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12641275 descr : res. descr ( ) ,
12651276 path,
12661277 accessible : child_accessible,
1278+ doc_visible : child_doc_visible,
12671279 note,
12681280 via_import,
12691281 } ) ;
@@ -1284,7 +1296,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12841296 // add the module to the lookup
12851297 if seen_modules. insert ( module. def_id ( ) ) {
12861298 if via_import { & mut worklist_via_import } else { & mut worklist }
1287- . push ( ( module, path_segments, child_accessible) ) ;
1299+ . push ( ( module, path_segments, child_accessible, child_doc_visible ) ) ;
12881300 }
12891301 }
12901302 }
@@ -2694,8 +2706,26 @@ fn show_candidates(
26942706 Vec :: new ( ) ;
26952707
26962708 candidates. iter ( ) . for_each ( |c| {
2697- ( if c. accessible { & mut accessible_path_strings } else { & mut inaccessible_path_strings } )
2698- . push ( ( pprust:: path_to_string ( & c. path ) , c. descr , c. did , & c. note , c. via_import ) )
2709+ if c. accessible {
2710+ // Don't suggest `#[doc(hidden)]` items from other crates
2711+ if c. doc_visible {
2712+ accessible_path_strings. push ( (
2713+ pprust:: path_to_string ( & c. path ) ,
2714+ c. descr ,
2715+ c. did ,
2716+ & c. note ,
2717+ c. via_import ,
2718+ ) )
2719+ }
2720+ } else {
2721+ inaccessible_path_strings. push ( (
2722+ pprust:: path_to_string ( & c. path ) ,
2723+ c. descr ,
2724+ c. did ,
2725+ & c. note ,
2726+ c. via_import ,
2727+ ) )
2728+ }
26992729 } ) ;
27002730
27012731 // we want consistent results across executions, but candidates are produced
@@ -2794,9 +2824,7 @@ fn show_candidates(
27942824 err. help ( msg) ;
27952825 }
27962826 true
2797- } else if !matches ! ( mode, DiagnosticMode :: Import ) {
2798- assert ! ( !inaccessible_path_strings. is_empty( ) ) ;
2799-
2827+ } else if !( inaccessible_path_strings. is_empty ( ) || matches ! ( mode, DiagnosticMode :: Import ) ) {
28002828 let prefix = if let DiagnosticMode :: Pattern = mode {
28012829 "you might have meant to match on "
28022830 } else {
0 commit comments