1
+ use crate :: imports:: ImportKind ;
2
+ use crate :: NameBinding ;
3
+ use crate :: NameBindingKind ;
4
+ use crate :: Resolver ;
1
5
use rustc_ast:: ast;
2
6
use rustc_ast:: visit;
3
7
use rustc_ast:: visit:: Visitor ;
4
8
use rustc_ast:: Crate ;
5
9
use rustc_ast:: EnumDef ;
6
- use rustc_ast:: ForeignMod ;
7
10
use rustc_ast:: NodeId ;
8
11
use rustc_hir:: def_id:: LocalDefId ;
9
12
use rustc_hir:: def_id:: CRATE_DEF_ID ;
10
13
use rustc_middle:: middle:: privacy:: AccessLevel ;
11
- use rustc_middle:: ty:: Visibility ;
14
+ use rustc_middle:: ty:: DefIdTree ;
12
15
use rustc_span:: sym;
13
16
14
- use crate :: imports:: ImportKind ;
15
- use crate :: BindingKey ;
16
- use crate :: NameBinding ;
17
- use crate :: NameBindingKind ;
18
- use crate :: Resolver ;
19
-
20
17
pub struct AccessLevelsVisitor < ' r , ' a > {
21
18
r : & ' r mut Resolver < ' a > ,
22
- prev_level : Option < AccessLevel > ,
23
19
changed : bool ,
24
20
}
25
21
@@ -28,11 +24,10 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
28
24
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
29
25
/// need access to a TyCtxt for that.
30
26
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 } ;
33
28
34
29
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 ) ;
36
31
37
32
while visitor. changed {
38
33
visitor. reset ( ) ;
@@ -44,15 +39,17 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
44
39
45
40
fn reset ( & mut self ) {
46
41
self . changed = false ;
47
- self . prev_level = Some ( AccessLevel :: Public ) ;
48
42
}
49
43
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
51
45
/// level has to be Exported or Public.
52
46
/// 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 ) {
54
48
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
+ }
56
53
// Set the given binding access level to `AccessLevel::Public` and
57
54
// sets the rest of the `use` chain to `AccessLevel::Exported` until
58
55
// we hit the actual exported item.
@@ -72,28 +69,20 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
72
69
}
73
70
} ;
74
71
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) ;
97
86
}
98
87
}
99
88
}
@@ -127,97 +116,59 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
127
116
128
117
impl < ' r , ' ast > Visitor < ' ast > for AccessLevelsVisitor < ' ast , ' r > {
129
118
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 {
131
123
// Resolved in rustc_privacy when types are available
132
124
ast:: ItemKind :: Impl ( ..) => return ,
133
125
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
-
166
126
// Should be unreachable at this stage
167
127
ast:: ItemKind :: MacCall ( ..) => panic ! (
168
128
"ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
169
129
) ,
170
- } ;
171
130
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
+ }
173
137
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 ) ) ;
180
142
}
143
+ }
181
144
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) ;
183
147
visit:: walk_item ( self , item) ;
184
- self . prev_level = orig_level;
185
148
}
186
149
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
- }
194
150
ast:: ItemKind :: Enum ( EnumDef { ref variants } , _) => {
151
+ self . set_bindings_access_level ( def_id) ;
195
152
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 ( ) ;
201
155
for field in variant. data . fields ( ) {
202
156
self . set_access_level ( field. id , variant_level) ;
203
157
}
204
158
}
205
159
}
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
- }
210
160
161
+ ast:: ItemKind :: Struct ( ref def, _) | ast:: ItemKind :: Union ( ref def, _) => {
162
+ let inherited_level = self . r . access_levels . map . get ( & def_id) . copied ( ) ;
211
163
for field in def. fields ( ) {
212
164
if field. vis . kind . is_pub ( ) {
213
- self . set_access_level ( field. id , access_level ) ;
165
+ self . set_access_level ( field. id , inherited_level ) ;
214
166
}
215
167
}
216
168
}
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) ;
221
172
}
222
173
223
174
ast:: ItemKind :: ExternCrate ( ..)
@@ -229,9 +180,6 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
229
180
| ast:: ItemKind :: TraitAlias ( ..)
230
181
| ast:: ItemKind :: MacroDef ( ..)
231
182
| ast:: ItemKind :: Fn ( ..) => return ,
232
-
233
- // Unreachable kinds
234
- ast:: ItemKind :: Impl ( ..) | ast:: ItemKind :: MacCall ( ..) => unreachable ! ( ) ,
235
183
}
236
184
}
237
185
}
0 commit comments