@@ -100,6 +100,8 @@ pub(crate) struct ImportSuggestion {
100
100
pub descr : & ' static str ,
101
101
pub path : Path ,
102
102
pub accessible : bool ,
103
+ // false if the path traverses a foreign `#[doc(hidden)]` item.
104
+ pub doc_visible : bool ,
103
105
pub via_import : bool ,
104
106
/// An extra note that should be issued if this item is suggested
105
107
pub note : Option < String > ,
@@ -1146,10 +1148,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1146
1148
{
1147
1149
let mut candidates = Vec :: new ( ) ;
1148
1150
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
+ ) ] ;
1150
1158
let mut worklist_via_import = vec ! [ ] ;
1151
1159
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 ( ) {
1153
1161
None => worklist_via_import. pop ( ) ,
1154
1162
Some ( x) => Some ( x) ,
1155
1163
} {
@@ -1192,6 +1200,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1192
1200
}
1193
1201
}
1194
1202
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
+
1195
1211
// collect results based on the filter function
1196
1212
// avoid suggesting anything from the same module in which we are resolving
1197
1213
// avoid suggesting anything with a hygienic name
@@ -1200,7 +1216,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1200
1216
&& in_module != parent_scope. module
1201
1217
&& !ident. span . normalize_to_macros_2_0 ( ) . from_expansion ( )
1202
1218
{
1203
- let res = name_binding. res ( ) ;
1204
1219
if filter_fn ( res) {
1205
1220
// create the path
1206
1221
let mut segms = if lookup_ident. span . at_least_rust_2018 ( ) {
@@ -1214,10 +1229,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1214
1229
1215
1230
segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
1216
1231
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
- } ;
1221
1232
1222
1233
if child_accessible {
1223
1234
// Remove invisible match if exists
@@ -1257,6 +1268,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1257
1268
descr : res. descr ( ) ,
1258
1269
path,
1259
1270
accessible : child_accessible,
1271
+ doc_visible : child_doc_visible,
1260
1272
note,
1261
1273
via_import,
1262
1274
} ) ;
@@ -1277,7 +1289,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1277
1289
// add the module to the lookup
1278
1290
if seen_modules. insert ( module. def_id ( ) ) {
1279
1291
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 ) ) ;
1281
1293
}
1282
1294
}
1283
1295
}
@@ -2687,8 +2699,26 @@ fn show_candidates(
2687
2699
Vec :: new ( ) ;
2688
2700
2689
2701
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
+ }
2692
2722
} ) ;
2693
2723
2694
2724
// we want consistent results across executions, but candidates are produced
@@ -2787,9 +2817,7 @@ fn show_candidates(
2787
2817
err. help ( msg) ;
2788
2818
}
2789
2819
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 ) ) {
2793
2821
let prefix = if let DiagnosticMode :: Pattern = mode {
2794
2822
"you might have meant to match on "
2795
2823
} else {
0 commit comments