1+ use crate :: imports:: ImportKind ;
2+ use crate :: NameBinding ;
3+ use crate :: NameBindingKind ;
4+ use crate :: Resolver ;
15use rustc_ast:: ast;
26use rustc_ast:: visit;
37use rustc_ast:: visit:: Visitor ;
48use rustc_ast:: Crate ;
59use rustc_ast:: EnumDef ;
6- use rustc_ast:: ForeignMod ;
710use rustc_ast:: NodeId ;
811use rustc_hir:: def_id:: LocalDefId ;
912use rustc_hir:: def_id:: CRATE_DEF_ID ;
1013use rustc_middle:: middle:: privacy:: AccessLevel ;
11- use rustc_middle:: ty:: Visibility ;
14+ use rustc_middle:: ty:: DefIdTree ;
1215use rustc_span:: sym;
1316
14- use crate :: imports:: ImportKind ;
15- use crate :: BindingKey ;
16- use crate :: NameBinding ;
17- use crate :: NameBindingKind ;
18- use crate :: Resolver ;
19-
2017pub struct AccessLevelsVisitor < ' r , ' a > {
2118 r : & ' r mut Resolver < ' a > ,
22- prev_level : Option < AccessLevel > ,
2319 changed : bool ,
2420}
2521
@@ -28,11 +24,10 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
2824 /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
2925 /// need access to a TyCtxt for that.
3026 pub fn compute_access_levels < ' c > ( r : & ' r mut Resolver < ' a > , krate : & ' c Crate ) {
31- let mut visitor =
32- AccessLevelsVisitor { r, changed : false , prev_level : Some ( AccessLevel :: Public ) } ;
27+ let mut visitor = AccessLevelsVisitor { r, changed : false } ;
3328
3429 visitor. set_access_level_def_id ( CRATE_DEF_ID , Some ( AccessLevel :: Public ) ) ;
35- visitor. set_exports_access_level ( CRATE_DEF_ID ) ;
30+ visitor. set_bindings_access_level ( CRATE_DEF_ID ) ;
3631
3732 while visitor. changed {
3833 visitor. reset ( ) ;
@@ -44,15 +39,17 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
4439
4540 fn reset ( & mut self ) {
4641 self . changed = false ;
47- self . prev_level = Some ( AccessLevel :: Public ) ;
4842 }
4943
50- /// Update the access level of the exports of the given module accordingly. The module access
44+ /// Update the access level of the bindings in the given module accordingly. The module access
5145 /// level has to be Exported or Public.
5246 /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level).
53- fn set_exports_access_level ( & mut self , module_id : LocalDefId ) {
47+ fn set_bindings_access_level ( & mut self , module_id : LocalDefId ) {
5448 assert ! ( self . r. module_map. contains_key( &&module_id. to_def_id( ) ) ) ;
55-
49+ let module_level = self . r . access_levels . map . get ( & module_id) . copied ( ) ;
50+ if !module_level. is_some ( ) {
51+ return ;
52+ }
5653 // Set the given binding access level to `AccessLevel::Public` and
5754 // sets the rest of the `use` chain to `AccessLevel::Exported` until
5855 // we hit the actual exported item.
@@ -72,28 +69,20 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
7269 }
7370 } ;
7471
75- let module_level = self . r . access_levels . map . get ( & module_id) . copied ( ) ;
76- assert ! ( module_level >= Some ( AccessLevel :: Exported ) ) ;
77-
78- if let Some ( exports) = self . r . reexport_map . get ( & module_id) {
79- let pub_exports = exports
80- . iter ( )
81- . filter ( |ex| ex. vis == Visibility :: Public )
82- . cloned ( )
83- . collect :: < Vec < _ > > ( ) ;
84-
85- let module = self . r . get_module ( module_id. to_def_id ( ) ) . unwrap ( ) ;
86- for export in pub_exports. into_iter ( ) {
87- if let Some ( export_def_id) = export. res . opt_def_id ( ) . and_then ( |id| id. as_local ( ) ) {
88- self . set_access_level_def_id ( export_def_id, Some ( AccessLevel :: Exported ) ) ;
89- }
90-
91- if let Some ( ns) = export. res . ns ( ) {
92- let key = BindingKey { ident : export. ident , ns, disambiguator : 0 } ;
93- let name_res = self . r . resolution ( module, key) ;
94- if let Some ( binding) = name_res. borrow ( ) . binding ( ) {
95- set_import_binding_access_level ( self , binding, module_level)
96- }
72+ let module = self . r . get_module ( module_id. to_def_id ( ) ) . unwrap ( ) ;
73+ let resolutions = self . r . resolutions ( module) ;
74+
75+ for ( .., name_resolution) in resolutions. borrow ( ) . iter ( ) {
76+ if let Some ( binding) = name_resolution. borrow ( ) . binding ( ) && binding. vis . is_public ( ) && !binding. is_ambiguity ( ) {
77+ let access_level = match binding. is_import ( ) {
78+ true => {
79+ set_import_binding_access_level ( self , binding, module_level) ;
80+ Some ( AccessLevel :: Exported )
81+ } ,
82+ false => module_level,
83+ } ;
84+ if let Some ( def_id) = binding. res ( ) . opt_def_id ( ) . and_then ( |id| id. as_local ( ) ) {
85+ self . set_access_level_def_id ( def_id, access_level) ;
9786 }
9887 }
9988 }
@@ -127,97 +116,59 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
127116
128117impl < ' r , ' ast > Visitor < ' ast > for AccessLevelsVisitor < ' ast , ' r > {
129118 fn visit_item ( & mut self , item : & ' ast ast:: Item ) {
130- let inherited_item_level = match item. kind {
119+ let def_id = self . r . local_def_id ( item. id ) ;
120+ // Set access level of nested items.
121+ // If it's a mod, also make the visitor walk all of its items
122+ match item. kind {
131123 // Resolved in rustc_privacy when types are available
132124 ast:: ItemKind :: Impl ( ..) => return ,
133125
134- // Only exported `macro_rules!` items are public, but they always are
135- ast:: ItemKind :: MacroDef ( ref macro_def) if macro_def. macro_rules => {
136- let is_macro_export =
137- item. attrs . iter ( ) . any ( |attr| attr. has_name ( sym:: macro_export) ) ;
138- if is_macro_export { Some ( AccessLevel :: Public ) } else { None }
139- }
140-
141- // Foreign modules inherit level from parents.
142- ast:: ItemKind :: ForeignMod ( ..) => self . prev_level ,
143-
144- // Other `pub` items inherit levels from parents.
145- ast:: ItemKind :: ExternCrate ( ..)
146- | ast:: ItemKind :: Use ( ..)
147- | ast:: ItemKind :: Static ( ..)
148- | ast:: ItemKind :: Const ( ..)
149- | ast:: ItemKind :: Fn ( ..)
150- | ast:: ItemKind :: Mod ( ..)
151- | ast:: ItemKind :: GlobalAsm ( ..)
152- | ast:: ItemKind :: TyAlias ( ..)
153- | ast:: ItemKind :: Enum ( ..)
154- | ast:: ItemKind :: Struct ( ..)
155- | ast:: ItemKind :: Union ( ..)
156- | ast:: ItemKind :: Trait ( ..)
157- | ast:: ItemKind :: TraitAlias ( ..)
158- | ast:: ItemKind :: MacroDef ( ..) => {
159- if item. vis . kind . is_pub ( ) {
160- self . prev_level
161- } else {
162- None
163- }
164- }
165-
166126 // Should be unreachable at this stage
167127 ast:: ItemKind :: MacCall ( ..) => panic ! (
168128 "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
169129 ) ,
170- } ;
171130
172- let access_level = self . set_access_level ( item. id , inherited_item_level) ;
131+ // Foreign modules inherit level from parents.
132+ ast:: ItemKind :: ForeignMod ( ..) => {
133+ let parent_level =
134+ self . r . access_levels . map . get ( & self . r . local_parent ( def_id) ) . copied ( ) ;
135+ self . set_access_level ( item. id , parent_level) ;
136+ }
173137
174- // Set access level of nested items.
175- // If it's a mod, also make the visitor walk all of its items
176- match item. kind {
177- ast:: ItemKind :: Mod ( ..) => {
178- if access_level. is_some ( ) {
179- self . set_exports_access_level ( self . r . local_def_id ( item. id ) ) ;
138+ // Only exported `macro_rules!` items are public, but they always are
139+ ast:: ItemKind :: MacroDef ( ref macro_def) if macro_def. macro_rules => {
140+ if item. attrs . iter ( ) . any ( |attr| attr. has_name ( sym:: macro_export) ) {
141+ self . set_access_level ( item. id , Some ( AccessLevel :: Public ) ) ;
180142 }
143+ }
181144
182- let orig_level = std:: mem:: replace ( & mut self . prev_level , access_level) ;
145+ ast:: ItemKind :: Mod ( ..) => {
146+ self . set_bindings_access_level ( def_id) ;
183147 visit:: walk_item ( self , item) ;
184- self . prev_level = orig_level;
185148 }
186149
187- ast:: ItemKind :: ForeignMod ( ForeignMod { ref items, .. } ) => {
188- for nested in items {
189- if nested. vis . kind . is_pub ( ) {
190- self . set_access_level ( nested. id , access_level) ;
191- }
192- }
193- }
194150 ast:: ItemKind :: Enum ( EnumDef { ref variants } , _) => {
151+ self . set_bindings_access_level ( def_id) ;
195152 for variant in variants {
196- let variant_level = self . set_access_level ( variant. id , access_level) ;
197- if let Some ( ctor_id) = variant. data . ctor_id ( ) {
198- self . set_access_level ( ctor_id, access_level) ;
199- }
200-
153+ let variant_def_id = self . r . local_def_id ( variant. id ) ;
154+ let variant_level = self . r . access_levels . map . get ( & variant_def_id) . copied ( ) ;
201155 for field in variant. data . fields ( ) {
202156 self . set_access_level ( field. id , variant_level) ;
203157 }
204158 }
205159 }
206- ast:: ItemKind :: Struct ( ref def, _) | ast:: ItemKind :: Union ( ref def, _) => {
207- if let Some ( ctor_id) = def. ctor_id ( ) {
208- self . set_access_level ( ctor_id, access_level) ;
209- }
210160
161+ ast:: ItemKind :: Struct ( ref def, _) | ast:: ItemKind :: Union ( ref def, _) => {
162+ let inherited_level = self . r . access_levels . map . get ( & def_id) . copied ( ) ;
211163 for field in def. fields ( ) {
212164 if field. vis . kind . is_pub ( ) {
213- self . set_access_level ( field. id , access_level ) ;
165+ self . set_access_level ( field. id , inherited_level ) ;
214166 }
215167 }
216168 }
217- ast:: ItemKind :: Trait ( ref trait_kind) => {
218- for nested in trait_kind. items . iter ( ) {
219- self . set_access_level ( nested. id , access_level) ;
220- }
169+
170+ ast:: ItemKind :: Trait ( ..) => {
171+ self . set_bindings_access_level ( def_id) ;
221172 }
222173
223174 ast:: ItemKind :: ExternCrate ( ..)
@@ -229,9 +180,6 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
229180 | ast:: ItemKind :: TraitAlias ( ..)
230181 | ast:: ItemKind :: MacroDef ( ..)
231182 | ast:: ItemKind :: Fn ( ..) => return ,
232-
233- // Unreachable kinds
234- ast:: ItemKind :: Impl ( ..) | ast:: ItemKind :: MacCall ( ..) => unreachable ! ( ) ,
235183 }
236184 }
237185}
0 commit comments