11use crate :: core:: DocContext ;
2- use rustc_hir:: def:: DefKind ;
2+ use rustc_hir:: def:: { DefKind , Res } ;
33use rustc_hir:: def_id:: { DefId , DefIdSet } ;
44use rustc_middle:: ty:: TyCtxt ;
5+ use rustc_resolve:: Resolver ;
56
67// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
78
@@ -25,6 +26,10 @@ impl RustdocEffectiveVisibilities {
2526 define_method ! ( is_directly_public) ;
2627 define_method ! ( is_exported) ;
2728 define_method ! ( is_reachable) ;
29+
30+ pub ( crate ) fn init ( & mut self , extern_public : DefIdSet ) {
31+ self . extern_public = extern_public;
32+ }
2833}
2934
3035pub ( crate ) fn lib_embargo_visit_item ( cx : & mut DocContext < ' _ > , def_id : DefId ) {
@@ -37,6 +42,17 @@ pub(crate) fn lib_embargo_visit_item(cx: &mut DocContext<'_>, def_id: DefId) {
3742 . visit_item ( def_id)
3843}
3944
45+ pub ( crate ) fn early_lib_embargo_visit_item (
46+ resolver : & Resolver < ' _ > ,
47+ extern_public : & mut DefIdSet ,
48+ def_id : DefId ,
49+ is_mod : bool ,
50+ ) {
51+ assert ! ( !def_id. is_local( ) ) ;
52+ EarlyLibEmbargoVisitor { resolver, extern_public, visited_mods : Default :: default ( ) }
53+ . visit_item ( def_id, is_mod)
54+ }
55+
4056/// Similar to `librustc_privacy::EmbargoVisitor`, but also takes
4157/// specific rustdoc annotations into account (i.e., `doc(hidden)`)
4258struct LibEmbargoVisitor < ' a , ' tcx > {
@@ -47,6 +63,14 @@ struct LibEmbargoVisitor<'a, 'tcx> {
4763 visited_mods : DefIdSet ,
4864}
4965
66+ struct EarlyLibEmbargoVisitor < ' r , ' ra > {
67+ resolver : & ' r Resolver < ' ra > ,
68+ // Effective visibilities for reachable nodes
69+ extern_public : & ' r mut DefIdSet ,
70+ // Keeps track of already visited modules, in case a module re-exports its parent
71+ visited_mods : DefIdSet ,
72+ }
73+
5074impl LibEmbargoVisitor < ' _ , ' _ > {
5175 fn visit_mod ( & mut self , def_id : DefId ) {
5276 if !self . visited_mods . insert ( def_id) {
@@ -71,3 +95,28 @@ impl LibEmbargoVisitor<'_, '_> {
7195 }
7296 }
7397}
98+
99+ impl EarlyLibEmbargoVisitor < ' _ , ' _ > {
100+ fn visit_mod ( & mut self , def_id : DefId ) {
101+ if !self . visited_mods . insert ( def_id) {
102+ return ;
103+ }
104+
105+ for item in self . resolver . cstore ( ) . module_children_untracked ( def_id, self . resolver . sess ( ) ) {
106+ if let Some ( def_id) = item. res . opt_def_id ( ) {
107+ if item. vis . is_public ( ) {
108+ self . visit_item ( def_id, matches ! ( item. res, Res :: Def ( DefKind :: Mod , _) ) ) ;
109+ }
110+ }
111+ }
112+ }
113+
114+ fn visit_item ( & mut self , def_id : DefId , is_mod : bool ) {
115+ if !self . resolver . cstore ( ) . is_doc_hidden_untracked ( def_id) {
116+ self . extern_public . insert ( def_id) ;
117+ if is_mod {
118+ self . visit_mod ( def_id) ;
119+ }
120+ }
121+ }
122+ }
0 commit comments