@@ -7,8 +7,10 @@ use rustc_ast::EnumDef;
77use rustc_data_structures:: intern:: Interned ;
88use rustc_hir:: def_id:: LocalDefId ;
99use rustc_hir:: def_id:: CRATE_DEF_ID ;
10- use rustc_middle:: middle:: privacy:: { EffectiveVisibilities , EffectiveVisibility , Level } ;
11- use rustc_middle:: ty:: Visibility ;
10+ use rustc_middle:: middle:: privacy:: { EffectiveVisibilities , EffectiveVisibility } ;
11+ use rustc_middle:: middle:: privacy:: { IntoDefIdTree , Level } ;
12+ use rustc_middle:: ty:: { DefIdTree , Visibility } ;
13+ use std:: mem;
1214
1315type ImportId < ' a > = Interned < ' a , NameBinding < ' a > > ;
1416
@@ -29,31 +31,71 @@ impl ParentId<'_> {
2931
3032pub struct EffectiveVisibilitiesVisitor < ' r , ' a > {
3133 r : & ' r mut Resolver < ' a > ,
34+ def_effective_visibilities : EffectiveVisibilities ,
3235 /// While walking import chains we need to track effective visibilities per-binding, and def id
3336 /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
3437 /// bindings can correspond to a single def id in imports. So we keep a separate table.
3538 import_effective_visibilities : EffectiveVisibilities < ImportId < ' a > > ,
39+ // It's possible to recalculate this at any point, but it's relatively expensive.
40+ current_private_vis : Visibility ,
3641 changed : bool ,
3742}
3843
44+ impl Resolver < ' _ > {
45+ fn nearest_normal_mod ( & mut self , def_id : LocalDefId ) -> LocalDefId {
46+ self . get_nearest_non_block_module ( def_id. to_def_id ( ) ) . nearest_parent_mod ( ) . expect_local ( )
47+ }
48+
49+ fn private_vis_import ( & mut self , binding : ImportId < ' _ > ) -> Visibility {
50+ let NameBindingKind :: Import { import, .. } = binding. kind else { unreachable ! ( ) } ;
51+ Visibility :: Restricted (
52+ import
53+ . id ( )
54+ . map ( |id| self . nearest_normal_mod ( self . local_def_id ( id) ) )
55+ . unwrap_or ( CRATE_DEF_ID ) ,
56+ )
57+ }
58+
59+ fn private_vis_def ( & mut self , def_id : LocalDefId ) -> Visibility {
60+ // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent.
61+ let normal_mod_id = self . nearest_normal_mod ( def_id) ;
62+ if normal_mod_id == def_id {
63+ self . opt_local_parent ( def_id) . map_or ( Visibility :: Public , Visibility :: Restricted )
64+ } else {
65+ Visibility :: Restricted ( normal_mod_id)
66+ }
67+ }
68+ }
69+
70+ impl < ' a , ' b > IntoDefIdTree for & ' b mut Resolver < ' a > {
71+ type Tree = & ' b Resolver < ' a > ;
72+ fn tree ( self ) -> Self :: Tree {
73+ self
74+ }
75+ }
76+
3977impl < ' r , ' a > EffectiveVisibilitiesVisitor < ' r , ' a > {
4078 /// Fills the `Resolver::effective_visibilities` table with public & exported items
4179 /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
4280 /// need access to a TyCtxt for that.
4381 pub fn compute_effective_visibilities < ' c > ( r : & ' r mut Resolver < ' a > , krate : & ' c Crate ) {
4482 let mut visitor = EffectiveVisibilitiesVisitor {
4583 r,
84+ def_effective_visibilities : Default :: default ( ) ,
4685 import_effective_visibilities : Default :: default ( ) ,
86+ current_private_vis : Visibility :: Public ,
4787 changed : false ,
4888 } ;
4989
5090 visitor. update ( CRATE_DEF_ID , CRATE_DEF_ID ) ;
91+ visitor. current_private_vis = Visibility :: Restricted ( CRATE_DEF_ID ) ;
5192 visitor. set_bindings_effective_visibilities ( CRATE_DEF_ID ) ;
5293
5394 while visitor. changed {
5495 visitor. changed = false ;
5596 visit:: walk_crate ( & mut visitor, krate) ;
5697 }
98+ visitor. r . effective_visibilities = visitor. def_effective_visibilities ;
5799
58100 // Update visibilities for import def ids. These are not used during the
59101 // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
@@ -90,10 +132,6 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
90132 info ! ( "resolve::effective_visibilities: {:#?}" , r. effective_visibilities) ;
91133 }
92134
93- fn nearest_normal_mod ( & mut self , def_id : LocalDefId ) -> LocalDefId {
94- self . r . get_nearest_non_block_module ( def_id. to_def_id ( ) ) . nearest_parent_mod ( ) . expect_local ( )
95- }
96-
97135 /// Update effective visibilities of bindings in the given module,
98136 /// including their whole reexport chains.
99137 fn set_bindings_effective_visibilities ( & mut self , module_id : LocalDefId ) {
@@ -122,62 +160,47 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
122160 }
123161 }
124162
125- fn effective_vis ( & self , parent_id : ParentId < ' a > ) -> Option < EffectiveVisibility > {
126- match parent_id {
127- ParentId :: Def ( def_id) => self . r . effective_visibilities . effective_vis ( def_id) ,
128- ParentId :: Import ( binding) => self . import_effective_visibilities . effective_vis ( binding) ,
129- }
130- . copied ( )
163+ fn cheap_private_vis ( & self , parent_id : ParentId < ' _ > ) -> Option < Visibility > {
164+ matches ! ( parent_id, ParentId :: Def ( _) ) . then_some ( self . current_private_vis )
131165 }
132166
133- /// The update is guaranteed to not change the table and we can skip it.
134- fn is_noop_update (
135- & self ,
136- parent_id : ParentId < ' a > ,
137- nominal_vis : Visibility ,
138- default_vis : Visibility ,
139- ) -> bool {
140- nominal_vis == default_vis
141- || match parent_id {
142- ParentId :: Def ( def_id) => self . r . visibilities [ & def_id] ,
143- ParentId :: Import ( binding) => binding. vis . expect_local ( ) ,
144- } == default_vis
167+ fn effective_vis_or_private ( & mut self , parent_id : ParentId < ' a > ) -> EffectiveVisibility {
168+ // Private nodes are only added to the table for caching, they could be added or removed at
169+ // any moment without consequences, so we don't set `changed` to true when adding them.
170+ * match parent_id {
171+ ParentId :: Def ( def_id) => self
172+ . def_effective_visibilities
173+ . effective_vis_or_private ( def_id, || self . r . private_vis_def ( def_id) ) ,
174+ ParentId :: Import ( binding) => self
175+ . import_effective_visibilities
176+ . effective_vis_or_private ( binding, || self . r . private_vis_import ( binding) ) ,
177+ }
145178 }
146179
147180 fn update_import ( & mut self , binding : ImportId < ' a > , parent_id : ParentId < ' a > ) {
148- let NameBindingKind :: Import { import, .. } = binding. kind else { unreachable ! ( ) } ;
149181 let nominal_vis = binding. vis . expect_local ( ) ;
150- let default_vis = Visibility :: Restricted (
151- import
152- . id ( )
153- . map ( |id| self . nearest_normal_mod ( self . r . local_def_id ( id) ) )
154- . unwrap_or ( CRATE_DEF_ID ) ,
155- ) ;
156- if self . is_noop_update ( parent_id, nominal_vis, default_vis) {
157- return ;
158- }
182+ let private_vis = self . cheap_private_vis ( parent_id) ;
183+ let inherited_eff_vis = self . effective_vis_or_private ( parent_id) ;
159184 self . changed |= self . import_effective_visibilities . update (
160185 binding,
161186 nominal_vis,
162- default_vis ,
163- self . effective_vis ( parent_id ) ,
187+ |r| ( private_vis . unwrap_or_else ( || r . private_vis_import ( binding ) ) , r ) ,
188+ inherited_eff_vis ,
164189 parent_id. level ( ) ,
165- ResolverTree ( & self . r . definitions , & self . r . crate_loader ) ,
190+ & mut * self . r ,
166191 ) ;
167192 }
168193
169194 fn update_def ( & mut self , def_id : LocalDefId , nominal_vis : Visibility , parent_id : ParentId < ' a > ) {
170- let default_vis = Visibility :: Restricted ( self . nearest_normal_mod ( def_id) ) ;
171- if self . is_noop_update ( parent_id, nominal_vis, default_vis) {
172- return ;
173- }
174- self . changed |= self . r . effective_visibilities . update (
195+ let private_vis = self . cheap_private_vis ( parent_id) ;
196+ let inherited_eff_vis = self . effective_vis_or_private ( parent_id) ;
197+ self . changed |= self . def_effective_visibilities . update (
175198 def_id,
176199 nominal_vis,
177- if def_id == CRATE_DEF_ID { Visibility :: Public } else { default_vis } ,
178- self . effective_vis ( parent_id ) ,
200+ |r| ( private_vis . unwrap_or_else ( || r . private_vis_def ( def_id) ) , r ) ,
201+ inherited_eff_vis ,
179202 parent_id. level ( ) ,
180- ResolverTree ( & self . r . definitions , & self . r . crate_loader ) ,
203+ & mut * self . r ,
181204 ) ;
182205 }
183206
@@ -201,8 +224,11 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
201224 ) ,
202225
203226 ast:: ItemKind :: Mod ( ..) => {
227+ let prev_private_vis =
228+ mem:: replace ( & mut self . current_private_vis , Visibility :: Restricted ( def_id) ) ;
204229 self . set_bindings_effective_visibilities ( def_id) ;
205230 visit:: walk_item ( self , item) ;
231+ self . current_private_vis = prev_private_vis;
206232 }
207233
208234 ast:: ItemKind :: Enum ( EnumDef { ref variants } , _) => {
0 commit comments