@@ -98,6 +98,8 @@ pub(crate) struct ImportSuggestion {
98
98
pub descr : & ' static str ,
99
99
pub path : Path ,
100
100
pub accessible : bool ,
101
+ // false if the path traverses a foreign `#[doc(hidden)]` item.
102
+ pub doc_visible : bool ,
101
103
pub via_import : bool ,
102
104
/// An extra note that should be issued if this item is suggested
103
105
pub note : Option < String > ,
@@ -1153,10 +1155,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1153
1155
{
1154
1156
let mut candidates = Vec :: new ( ) ;
1155
1157
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
+ ) ] ;
1157
1165
let mut worklist_via_import = vec ! [ ] ;
1158
1166
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 ( ) {
1160
1168
None => worklist_via_import. pop ( ) ,
1161
1169
Some ( x) => Some ( x) ,
1162
1170
} {
@@ -1199,6 +1207,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1199
1207
}
1200
1208
}
1201
1209
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
+
1202
1218
// collect results based on the filter function
1203
1219
// avoid suggesting anything from the same module in which we are resolving
1204
1220
// avoid suggesting anything with a hygienic name
@@ -1207,7 +1223,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1207
1223
&& in_module != parent_scope. module
1208
1224
&& !ident. span . normalize_to_macros_2_0 ( ) . from_expansion ( )
1209
1225
{
1210
- let res = name_binding. res ( ) ;
1211
1226
if filter_fn ( res) {
1212
1227
// create the path
1213
1228
let mut segms = if lookup_ident. span . at_least_rust_2018 ( ) {
@@ -1221,10 +1236,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1221
1236
1222
1237
segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
1223
1238
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
- } ;
1228
1239
1229
1240
if child_accessible {
1230
1241
// Remove invisible match if exists
@@ -1264,6 +1275,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1264
1275
descr : res. descr ( ) ,
1265
1276
path,
1266
1277
accessible : child_accessible,
1278
+ doc_visible : child_doc_visible,
1267
1279
note,
1268
1280
via_import,
1269
1281
} ) ;
@@ -1284,7 +1296,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1284
1296
// add the module to the lookup
1285
1297
if seen_modules. insert ( module. def_id ( ) ) {
1286
1298
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 ) ) ;
1288
1300
}
1289
1301
}
1290
1302
}
@@ -2694,8 +2706,26 @@ fn show_candidates(
2694
2706
Vec :: new ( ) ;
2695
2707
2696
2708
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
+ }
2699
2729
} ) ;
2700
2730
2701
2731
// we want consistent results across executions, but candidates are produced
@@ -2794,9 +2824,7 @@ fn show_candidates(
2794
2824
err. help ( msg) ;
2795
2825
}
2796
2826
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 ) ) {
2800
2828
let prefix = if let DiagnosticMode :: Pattern = mode {
2801
2829
"you might have meant to match on "
2802
2830
} else {
0 commit comments