22use std:: sync:: Arc ;
33
44use crate :: clean:: cfg:: Cfg ;
5+ use crate :: clean:: inline:: { load_attrs, merge_attrs} ;
56use crate :: clean:: { Crate , Item } ;
67use crate :: core:: DocContext ;
78use crate :: fold:: DocFolder ;
89use crate :: passes:: Pass ;
910
11+ use rustc_hir:: def_id:: LocalDefId ;
12+
1013pub ( crate ) const PROPAGATE_DOC_CFG : Pass = Pass {
1114 name : "propagate-doc-cfg" ,
1215 run : propagate_doc_cfg,
1316 description : "propagates `#[doc(cfg(...))]` to child items" ,
1417} ;
1518
16- pub ( crate ) fn propagate_doc_cfg ( cr : Crate , _ : & mut DocContext < ' _ > ) -> Crate {
17- CfgPropagator { parent_cfg : None } . fold_crate ( cr)
19+ pub ( crate ) fn propagate_doc_cfg ( cr : Crate , cx : & mut DocContext < ' _ > ) -> Crate {
20+ CfgPropagator { parent_cfg : None , parent : None , cx } . fold_crate ( cr)
1821}
1922
20- struct CfgPropagator {
23+ struct CfgPropagator < ' a , ' tcx > {
2124 parent_cfg : Option < Arc < Cfg > > ,
25+ parent : Option < LocalDefId > ,
26+ cx : & ' a mut DocContext < ' tcx > ,
2227}
2328
24- impl DocFolder for CfgPropagator {
29+ impl < ' a , ' tcx > DocFolder for CfgPropagator < ' a , ' tcx > {
2530 fn fold_item ( & mut self , mut item : Item ) -> Option < Item > {
2631 let old_parent_cfg = self . parent_cfg . clone ( ) ;
2732
33+ if item. kind . is_non_assoc ( ) &&
34+ let Some ( def_id) = item. item_id . as_def_id ( ) . and_then ( |def_id| def_id. as_local ( ) ) {
35+ let hir = self . cx . tcx . hir ( ) ;
36+ let hir_id = hir. local_def_id_to_hir_id ( def_id) ;
37+ let expected_parent = hir. get_parent_item ( hir_id) ;
38+
39+ // If parents are different, it means that `item` is a reexport and we need to compute
40+ // the actual `cfg` by iterating through its "real" parents.
41+ if self . parent != Some ( expected_parent) {
42+ let mut attrs = Vec :: new ( ) ;
43+ for ( parent_hir_id, _) in hir. parent_iter ( hir_id) {
44+ let def_id = hir. local_def_id ( parent_hir_id) . to_def_id ( ) ;
45+ attrs. extend_from_slice ( load_attrs ( self . cx , def_id) ) ;
46+ }
47+ let ( _, cfg) =
48+ merge_attrs ( self . cx , None , item. attrs . other_attrs . as_slice ( ) , Some ( & attrs) ) ;
49+ item. cfg = cfg;
50+ }
51+ }
2852 let new_cfg = match ( self . parent_cfg . take ( ) , item. cfg . take ( ) ) {
2953 ( None , None ) => None ,
3054 ( Some ( rc) , None ) | ( None , Some ( rc) ) => Some ( rc) ,
@@ -37,8 +61,15 @@ impl DocFolder for CfgPropagator {
3761 self . parent_cfg = new_cfg. clone ( ) ;
3862 item. cfg = new_cfg;
3963
64+ let old_parent =
65+ if let Some ( def_id) = item. item_id . as_def_id ( ) . and_then ( |def_id| def_id. as_local ( ) ) {
66+ self . parent . replace ( def_id)
67+ } else {
68+ self . parent . take ( )
69+ } ;
4070 let result = self . fold_item_recur ( item) ;
4171 self . parent_cfg = old_parent_cfg;
72+ self . parent = old_parent;
4273
4374 Some ( result)
4475 }
0 commit comments