@@ -100,6 +100,8 @@ pub(crate) struct ImportSuggestion {
100100 pub descr : & ' static str ,
101101 pub path : Path ,
102102 pub accessible : bool ,
103+ // false if the path traverses a foreign `#[doc(hidden)]` item.
104+ pub doc_visible : bool ,
103105 pub via_import : bool ,
104106 /// An extra note that should be issued if this item is suggested
105107 pub note : Option < String > ,
@@ -1146,10 +1148,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11461148 {
11471149 let mut candidates = Vec :: new ( ) ;
11481150 let mut seen_modules = FxHashSet :: default ( ) ;
1149- let mut worklist = vec ! [ ( start_module, ThinVec :: <ast:: PathSegment >:: new( ) , true ) ] ;
1151+ let start_did = start_module. def_id ( ) ;
1152+ let mut worklist = vec ! [ (
1153+ start_module,
1154+ ThinVec :: <ast:: PathSegment >:: new( ) ,
1155+ true ,
1156+ start_did. is_local( ) || !self . tcx. is_doc_hidden( start_did) ,
1157+ ) ] ;
11501158 let mut worklist_via_import = vec ! [ ] ;
11511159
1152- while let Some ( ( in_module, path_segments, accessible) ) = match worklist. pop ( ) {
1160+ while let Some ( ( in_module, path_segments, accessible, doc_visible ) ) = match worklist. pop ( ) {
11531161 None => worklist_via_import. pop ( ) ,
11541162 Some ( x) => Some ( x) ,
11551163 } {
@@ -1192,6 +1200,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11921200 }
11931201 }
11941202
1203+ let res = name_binding. res ( ) ;
1204+ let did = match res {
1205+ Res :: Def ( DefKind :: Ctor ( ..) , did) => this. tcx . opt_parent ( did) ,
1206+ _ => res. opt_def_id ( ) ,
1207+ } ;
1208+ let child_doc_visible = doc_visible
1209+ && ( did. map_or ( true , |did| did. is_local ( ) || !this. tcx . is_doc_hidden ( did) ) ) ;
1210+
11951211 // collect results based on the filter function
11961212 // avoid suggesting anything from the same module in which we are resolving
11971213 // avoid suggesting anything with a hygienic name
@@ -1200,7 +1216,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12001216 && in_module != parent_scope. module
12011217 && !ident. span . normalize_to_macros_2_0 ( ) . from_expansion ( )
12021218 {
1203- let res = name_binding. res ( ) ;
12041219 if filter_fn ( res) {
12051220 // create the path
12061221 let mut segms = if lookup_ident. span . at_least_rust_2018 ( ) {
@@ -1214,10 +1229,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12141229
12151230 segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
12161231 let path = Path { span : name_binding. span , segments : segms, tokens : None } ;
1217- let did = match res {
1218- Res :: Def ( DefKind :: Ctor ( ..) , did) => this. tcx . opt_parent ( did) ,
1219- _ => res. opt_def_id ( ) ,
1220- } ;
12211232
12221233 if child_accessible {
12231234 // Remove invisible match if exists
@@ -1257,6 +1268,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12571268 descr : res. descr ( ) ,
12581269 path,
12591270 accessible : child_accessible,
1271+ doc_visible : child_doc_visible,
12601272 note,
12611273 via_import,
12621274 } ) ;
@@ -1277,7 +1289,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12771289 // add the module to the lookup
12781290 if seen_modules. insert ( module. def_id ( ) ) {
12791291 if via_import { & mut worklist_via_import } else { & mut worklist }
1280- . push ( ( module, path_segments, child_accessible) ) ;
1292+ . push ( ( module, path_segments, child_accessible, child_doc_visible ) ) ;
12811293 }
12821294 }
12831295 }
@@ -2687,8 +2699,26 @@ fn show_candidates(
26872699 Vec :: new ( ) ;
26882700
26892701 candidates. iter ( ) . for_each ( |c| {
2690- ( if c. accessible { & mut accessible_path_strings } else { & mut inaccessible_path_strings } )
2691- . push ( ( pprust:: path_to_string ( & c. path ) , c. descr , c. did , & c. note , c. via_import ) )
2702+ if c. accessible {
2703+ // Don't suggest `#[doc(hidden)]` items from other crates
2704+ if c. doc_visible {
2705+ accessible_path_strings. push ( (
2706+ pprust:: path_to_string ( & c. path ) ,
2707+ c. descr ,
2708+ c. did ,
2709+ & c. note ,
2710+ c. via_import ,
2711+ ) )
2712+ }
2713+ } else {
2714+ inaccessible_path_strings. push ( (
2715+ pprust:: path_to_string ( & c. path ) ,
2716+ c. descr ,
2717+ c. did ,
2718+ & c. note ,
2719+ c. via_import ,
2720+ ) )
2721+ }
26922722 } ) ;
26932723
26942724 // we want consistent results across executions, but candidates are produced
@@ -2787,9 +2817,7 @@ fn show_candidates(
27872817 err. help ( msg) ;
27882818 }
27892819 true
2790- } else if !matches ! ( mode, DiagnosticMode :: Import ) {
2791- assert ! ( !inaccessible_path_strings. is_empty( ) ) ;
2792-
2820+ } else if !( inaccessible_path_strings. is_empty ( ) || matches ! ( mode, DiagnosticMode :: Import ) ) {
27932821 let prefix = if let DiagnosticMode :: Pattern = mode {
27942822 "you might have meant to match on "
27952823 } else {
0 commit comments