@@ -19,6 +19,13 @@ use std::{iter, mem};
19
19
use crate :: clean:: { cfg:: Cfg , reexport_chain, AttributesExt , NestedAttributesExt } ;
20
20
use crate :: core;
21
21
22
+ #[ derive( Debug ) ]
23
+ pub ( crate ) struct ItemEntry < ' hir > {
24
+ pub ( crate ) item : & ' hir hir:: Item < ' hir > ,
25
+ pub ( crate ) renamed : Option < Symbol > ,
26
+ pub ( crate ) import_id : Option < LocalDefId > ,
27
+ }
28
+
22
29
/// This module is used to store stuff from Rust's AST in a more convenient
23
30
/// manner (and with prettier names) before cleaning.
24
31
#[ derive( Debug ) ]
@@ -31,10 +38,7 @@ pub(crate) struct Module<'hir> {
31
38
pub ( crate ) import_id : Option < LocalDefId > ,
32
39
/// The key is the item `ItemId` and the value is: (item, renamed, import_id).
33
40
/// We use `FxIndexMap` to keep the insert order.
34
- pub ( crate ) items : FxIndexMap <
35
- ( LocalDefId , Option < Symbol > ) ,
36
- ( & ' hir hir:: Item < ' hir > , Option < Symbol > , Option < LocalDefId > ) ,
37
- > ,
41
+ pub ( crate ) items : FxIndexMap < ( LocalDefId , Option < Symbol > ) , ItemEntry < ' hir > > ,
38
42
pub ( crate ) foreigns : Vec < ( & ' hir hir:: ForeignItem < ' hir > , Option < Symbol > ) > ,
39
43
}
40
44
@@ -107,6 +111,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
107
111
modules : Vec < Module < ' tcx > > ,
108
112
is_importable_from_parent : bool ,
109
113
inside_body : bool ,
114
+ ignored_items : usize ,
110
115
}
111
116
112
117
impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
@@ -131,6 +136,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
131
136
modules : vec ! [ om] ,
132
137
is_importable_from_parent : true ,
133
138
inside_body : false ,
139
+ ignored_items : 0 ,
134
140
}
135
141
}
136
142
@@ -165,7 +171,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
165
171
inserted. insert ( def_id)
166
172
{
167
173
let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
168
- top_level_module. items . insert ( ( local_def_id, Some ( item. ident . name ) ) , ( item, None , None ) ) ;
174
+ top_level_module. items . insert ( ( local_def_id, Some ( item. ident . name ) ) , ItemEntry {
175
+ item,
176
+ renamed : None ,
177
+ import_id : None ,
178
+ } ) ;
169
179
}
170
180
}
171
181
@@ -263,9 +273,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
263
273
} ;
264
274
265
275
let use_attrs = tcx. hir ( ) . attrs ( tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ) ;
266
- // Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
267
- let is_no_inline = use_attrs. lists ( sym:: doc) . has_word ( sym:: no_inline)
268
- || use_attrs. lists ( sym:: doc) . has_word ( sym:: hidden) ;
276
+ let is_no_inline = use_attrs. lists ( sym:: doc) . has_word ( sym:: no_inline) ;
269
277
270
278
// For cross-crate impl inlining we need to know whether items are
271
279
// reachable in documentation -- a previously unreachable item can be
@@ -280,12 +288,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
280
288
return false ;
281
289
} ;
282
290
283
- let is_private =
284
- !self . cx . cache . effective_visibilities . is_directly_public ( self . cx . tcx , ori_res_did) ;
285
- let is_hidden = inherits_doc_hidden ( self . cx . tcx , res_did, None ) ;
291
+ let is_private = !self . cx . cache . effective_visibilities . is_directly_public ( tcx, ori_res_did) ;
292
+ let is_hidden = tcx. is_doc_hidden ( res_did) || inherits_doc_hidden ( tcx, res_did, None ) ;
286
293
287
294
// Only inline if requested or if the item would otherwise be stripped.
288
- if ( !please_inline && !is_private && !is_hidden) || is_no_inline {
295
+ if is_no_inline || ( !please_inline && !is_private && !is_hidden) {
289
296
return false ;
290
297
}
291
298
@@ -298,8 +305,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
298
305
. cx
299
306
. cache
300
307
. effective_visibilities
301
- . is_directly_public ( self . cx . tcx , item_def_id. to_def_id ( ) ) &&
302
- !inherits_doc_hidden ( self . cx . tcx , item_def_id, None )
308
+ . is_directly_public ( tcx, item_def_id. to_def_id ( ) ) &&
309
+ !tcx. is_doc_hidden ( item_def_id) &&
310
+ !inherits_doc_hidden ( tcx, item_def_id, None )
303
311
{
304
312
// The imported item is public and not `doc(hidden)` so no need to inline it.
305
313
return false ;
@@ -312,22 +320,25 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
312
320
let ret = match tcx. hir ( ) . get_by_def_id ( res_did) {
313
321
Node :: Item ( & hir:: Item { kind : hir:: ItemKind :: Mod ( ref m) , .. } ) if glob => {
314
322
let prev = mem:: replace ( & mut self . inlining , true ) ;
323
+ let prev_ignored = self . ignored_items ;
315
324
for & i in m. item_ids {
316
- let i = self . cx . tcx . hir ( ) . item ( i) ;
317
- self . visit_item_inner ( i, None , Some ( def_id) ) ;
325
+ let i = tcx. hir ( ) . item ( i) ;
326
+ self . visit_item_inner ( i, None , Some ( def_id) , true ) ;
318
327
}
319
328
self . inlining = prev;
320
- true
329
+ let inline = self . ignored_items - prev_ignored == 0 ;
330
+ self . ignored_items = prev_ignored;
331
+ inline
321
332
}
322
333
Node :: Item ( it) if !glob => {
323
334
let prev = mem:: replace ( & mut self . inlining , true ) ;
324
- self . visit_item_inner ( it, renamed, Some ( def_id) ) ;
335
+ self . visit_item_inner ( it, renamed, Some ( def_id) , false ) ;
325
336
self . inlining = prev;
326
337
true
327
338
}
328
339
Node :: ForeignItem ( it) if !glob => {
329
340
let prev = mem:: replace ( & mut self . inlining , true ) ;
330
- self . visit_foreign_item_inner ( it, renamed) ;
341
+ self . visit_foreign_item_inner ( it, renamed, false ) ;
331
342
self . inlining = prev;
332
343
true
333
344
}
@@ -343,6 +354,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
343
354
item : & ' tcx hir:: Item < ' _ > ,
344
355
renamed : Option < Symbol > ,
345
356
parent_id : Option < LocalDefId > ,
357
+ from_glob_reexport : bool ,
346
358
) {
347
359
if self . is_importable_from_parent
348
360
// If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
@@ -355,11 +367,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
355
367
_ => false ,
356
368
}
357
369
{
358
- self . modules
359
- . last_mut ( )
360
- . unwrap ( )
361
- . items
362
- . insert ( ( item. owner_id . def_id , renamed) , ( item, renamed, parent_id) ) ;
370
+ if !from_glob_reexport || !self . cx . tcx . is_doc_hidden ( item. owner_id . to_def_id ( ) ) {
371
+ self . modules . last_mut ( ) . unwrap ( ) . items . insert (
372
+ ( item. owner_id . def_id , renamed) ,
373
+ ItemEntry { item, renamed, import_id : parent_id } ,
374
+ ) ;
375
+ } else {
376
+ self . ignored_items += 1 ;
377
+ }
363
378
}
364
379
}
365
380
@@ -368,6 +383,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
368
383
item : & ' tcx hir:: Item < ' _ > ,
369
384
renamed : Option < Symbol > ,
370
385
import_id : Option < LocalDefId > ,
386
+ from_glob_reexport : bool ,
371
387
) {
372
388
debug ! ( "visiting item {:?}" , item) ;
373
389
if self . inside_body {
@@ -386,7 +402,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
386
402
// them up regardless of where they're located.
387
403
impl_. of_trait . is_none ( )
388
404
{
389
- self . add_to_current_mod ( item, None , None ) ;
405
+ self . add_to_current_mod ( item, None , None , false ) ;
390
406
}
391
407
return ;
392
408
}
@@ -404,7 +420,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
404
420
hir:: ItemKind :: ForeignMod { items, .. } => {
405
421
for item in items {
406
422
let item = tcx. hir ( ) . foreign_item ( item. id ) ;
407
- self . visit_foreign_item_inner ( item, None ) ;
423
+ self . visit_foreign_item_inner ( item, None , from_glob_reexport ) ;
408
424
}
409
425
}
410
426
// If we're inlining, skip private items.
@@ -419,6 +435,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
419
435
continue ;
420
436
}
421
437
438
+ if from_glob_reexport &&
439
+ tcx. is_doc_hidden ( def_id) &&
440
+ let Some ( res_def_id) = res. opt_def_id ( ) &&
441
+ tcx. is_doc_hidden ( res_def_id)
442
+ {
443
+ self . ignored_items += 1 ;
444
+ continue ;
445
+ }
446
+
422
447
let attrs =
423
448
tcx. hir ( ) . attrs ( tcx. hir ( ) . local_def_id_to_hir_id ( item. owner_id . def_id ) ) ;
424
449
@@ -444,7 +469,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
444
469
}
445
470
}
446
471
447
- self . add_to_current_mod ( item, renamed, import_id) ;
472
+ self . add_to_current_mod ( item, renamed, import_id, false ) ;
448
473
}
449
474
}
450
475
hir:: ItemKind :: Macro ( ref macro_def, _) => {
@@ -464,7 +489,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
464
489
let nonexported = !tcx. has_attr ( def_id, sym:: macro_export) ;
465
490
466
491
if is_macro_2_0 || nonexported || self . inlining {
467
- self . add_to_current_mod ( item, renamed, import_id) ;
492
+ self . add_to_current_mod ( item, renamed, import_id, from_glob_reexport ) ;
468
493
}
469
494
}
470
495
hir:: ItemKind :: Mod ( ref m) => {
@@ -483,7 +508,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
483
508
| hir:: ItemKind :: Static ( ..)
484
509
| hir:: ItemKind :: Trait ( ..)
485
510
| hir:: ItemKind :: TraitAlias ( ..) => {
486
- self . add_to_current_mod ( item, renamed, import_id) ;
511
+ self . add_to_current_mod ( item, renamed, import_id, from_glob_reexport ) ;
487
512
}
488
513
hir:: ItemKind :: OpaqueTy ( hir:: OpaqueTy {
489
514
origin : hir:: OpaqueTyOrigin :: AsyncFn ( _) | hir:: OpaqueTyOrigin :: FnReturn ( _) ,
@@ -495,14 +520,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
495
520
// Underscore constants do not correspond to a nameable item and
496
521
// so are never useful in documentation.
497
522
if name != kw:: Underscore {
498
- self . add_to_current_mod ( item, renamed, import_id) ;
523
+ self . add_to_current_mod ( item, renamed, import_id, from_glob_reexport ) ;
499
524
}
500
525
}
501
526
hir:: ItemKind :: Impl ( impl_) => {
502
527
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
503
528
// them up regardless of where they're located.
504
529
if !self . inlining && impl_. of_trait . is_none ( ) {
505
- self . add_to_current_mod ( item, None , None ) ;
530
+ self . add_to_current_mod ( item, None , None , false ) ;
506
531
}
507
532
}
508
533
}
@@ -512,10 +537,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
512
537
& mut self ,
513
538
item : & ' tcx hir:: ForeignItem < ' _ > ,
514
539
renamed : Option < Symbol > ,
540
+ from_glob_reexport : bool ,
515
541
) {
516
542
// If inlining we only want to include public functions.
517
543
if !self . inlining || self . cx . tcx . visibility ( item. owner_id ) . is_public ( ) {
518
- self . modules . last_mut ( ) . unwrap ( ) . foreigns . push ( ( item, renamed) ) ;
544
+ if !from_glob_reexport || !self . cx . tcx . is_doc_hidden ( item. owner_id . to_def_id ( ) ) {
545
+ self . modules . last_mut ( ) . unwrap ( ) . foreigns . push ( ( item, renamed) ) ;
546
+ } else {
547
+ self . ignored_items += 1 ;
548
+ }
519
549
}
520
550
}
521
551
@@ -549,7 +579,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
549
579
}
550
580
551
581
fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
552
- self . visit_item_inner ( i, None , None ) ;
582
+ self . visit_item_inner ( i, None , None , false ) ;
553
583
let new_value = self . is_importable_from_parent
554
584
&& matches ! (
555
585
i. kind,
0 commit comments