1
1
//! A pass that checks to make sure private fields and methods aren't used
2
2
//! outside their scopes. This pass will also generate a set of exported items
3
3
//! which are available for use externally when compiled as a library.
4
- use crate :: ty:: Visibility ;
4
+ use crate :: ty:: { DefIdTree , Visibility } ;
5
5
use rustc_data_structures:: fx:: FxHashMap ;
6
6
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
7
7
use rustc_macros:: HashStable ;
8
8
use rustc_query_system:: ich:: StableHashingContext ;
9
- use rustc_span:: def_id:: LocalDefId ;
9
+ use rustc_span:: def_id:: { DefId , LocalDefId } ;
10
10
use std:: hash:: Hash ;
11
11
12
12
/// Represents the levels of accessibility an item can have.
@@ -27,26 +27,36 @@ pub enum AccessLevel {
27
27
Public ,
28
28
}
29
29
30
- #[ derive( Clone , Copy , PartialEq , Eq , Debug , HashStable , Default ) ]
30
+ impl AccessLevel {
31
+ pub fn all_levels ( ) -> [ AccessLevel ; 4 ] {
32
+ [
33
+ AccessLevel :: Public ,
34
+ AccessLevel :: Exported ,
35
+ AccessLevel :: Reachable ,
36
+ AccessLevel :: ReachableFromImplTrait ,
37
+ ]
38
+ }
39
+ }
40
+
41
+ #[ derive( Clone , Copy , PartialEq , Eq , Debug , HashStable ) ]
31
42
pub struct EffectiveVisibility {
32
- public : Option < Visibility > ,
33
- exported : Option < Visibility > ,
34
- reachable : Option < Visibility > ,
35
- reachable_from_impl_trait : Option < Visibility > ,
43
+ public : Visibility ,
44
+ exported : Visibility ,
45
+ reachable : Visibility ,
46
+ reachable_from_impl_trait : Visibility ,
36
47
}
37
48
38
49
impl EffectiveVisibility {
39
- pub fn get ( & self , tag : AccessLevel ) -> Option < & Visibility > {
50
+ pub fn get ( & self , tag : AccessLevel ) -> & Visibility {
40
51
match tag {
41
52
AccessLevel :: Public => & self . public ,
42
53
AccessLevel :: Exported => & self . exported ,
43
54
AccessLevel :: Reachable => & self . reachable ,
44
55
AccessLevel :: ReachableFromImplTrait => & self . reachable_from_impl_trait ,
45
56
}
46
- . as_ref ( )
47
57
}
48
58
49
- fn get_mut ( & mut self , tag : AccessLevel ) -> & mut Option < Visibility > {
59
+ fn get_mut ( & mut self , tag : AccessLevel ) -> & mut Visibility {
50
60
match tag {
51
61
AccessLevel :: Public => & mut self . public ,
52
62
AccessLevel :: Exported => & mut self . exported ,
@@ -56,7 +66,30 @@ impl EffectiveVisibility {
56
66
}
57
67
58
68
pub fn is_public_at_level ( & self , tag : AccessLevel ) -> bool {
59
- self . get ( tag) . map_or ( false , |vis| vis. is_public ( ) )
69
+ self . get ( tag) . is_public ( )
70
+ }
71
+
72
+ fn update ( & mut self , vis : Visibility , tag : AccessLevel , tree : impl DefIdTree ) -> bool {
73
+ let mut changed = false ;
74
+ for level in AccessLevel :: all_levels ( ) {
75
+ if level <= tag {
76
+ let current_effective_vis = self . get_mut ( level) ;
77
+ if * current_effective_vis != vis && vis. is_at_least ( * current_effective_vis, tree) {
78
+ changed = true ;
79
+ * current_effective_vis = vis;
80
+ }
81
+ }
82
+ }
83
+ changed
84
+ }
85
+
86
+ fn from_vis ( vis : Visibility ) -> EffectiveVisibility {
87
+ EffectiveVisibility {
88
+ public : vis,
89
+ exported : vis,
90
+ reachable : vis,
91
+ reachable_from_impl_trait : vis,
92
+ }
60
93
}
61
94
}
62
95
@@ -89,12 +122,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
89
122
90
123
pub fn get_access_level ( & self , id : Id ) -> Option < AccessLevel > {
91
124
self . get_effective_vis ( id) . and_then ( |effective_vis| {
92
- for level in [
93
- AccessLevel :: Public ,
94
- AccessLevel :: Exported ,
95
- AccessLevel :: Reachable ,
96
- AccessLevel :: ReachableFromImplTrait ,
97
- ] {
125
+ for level in AccessLevel :: all_levels ( ) {
98
126
if effective_vis. is_public_at_level ( level) {
99
127
return Some ( level) ;
100
128
}
@@ -103,21 +131,6 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
103
131
} )
104
132
}
105
133
106
- pub fn set_access_level ( & mut self , id : Id , tag : AccessLevel ) {
107
- let mut effective_vis = self . get_effective_vis ( id) . copied ( ) . unwrap_or_default ( ) ;
108
- for level in [
109
- AccessLevel :: Public ,
110
- AccessLevel :: Exported ,
111
- AccessLevel :: Reachable ,
112
- AccessLevel :: ReachableFromImplTrait ,
113
- ] {
114
- if level <= tag {
115
- * effective_vis. get_mut ( level) = Some ( Visibility :: Public ) ;
116
- }
117
- }
118
- self . map . insert ( id, effective_vis) ;
119
- }
120
-
121
134
pub fn get_effective_vis ( & self , id : Id ) -> Option < & EffectiveVisibility > {
122
135
self . map . get ( & id)
123
136
}
@@ -129,6 +142,65 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
129
142
pub fn map_id < OutId : Hash + Eq + Copy > ( & self , f : impl Fn ( Id ) -> OutId ) -> AccessLevels < OutId > {
130
143
AccessLevels { map : self . map . iter ( ) . map ( |( k, v) | ( f ( * k) , * v) ) . collect ( ) }
131
144
}
145
+
146
+ pub fn set_access_level (
147
+ & mut self ,
148
+ id : Id ,
149
+ default_vis : impl FnOnce ( ) -> Visibility ,
150
+ tag : AccessLevel ,
151
+ ) {
152
+ let mut effective_vis = self
153
+ . get_effective_vis ( id)
154
+ . copied ( )
155
+ . unwrap_or_else ( || EffectiveVisibility :: from_vis ( default_vis ( ) ) ) ;
156
+ for level in AccessLevel :: all_levels ( ) {
157
+ if level <= tag {
158
+ * effective_vis. get_mut ( level) = Visibility :: Public ;
159
+ }
160
+ }
161
+ self . map . insert ( id, effective_vis) ;
162
+ }
163
+ }
164
+
165
+ impl < Id : Hash + Eq + Copy + Into < DefId > > AccessLevels < Id > {
166
+ // `parent_id` is not necessarily a parent in source code tree,
167
+ // it is the node from which the maximum effective visibility is inherited.
168
+ pub fn update (
169
+ & mut self ,
170
+ id : Id ,
171
+ nominal_vis : Visibility ,
172
+ default_vis : impl FnOnce ( ) -> Visibility ,
173
+ parent_id : Id ,
174
+ tag : AccessLevel ,
175
+ tree : impl DefIdTree ,
176
+ ) -> Result < bool , ( ) > {
177
+ let mut changed = false ;
178
+ let mut current_effective_vis = self
179
+ . get_effective_vis ( id)
180
+ . copied ( )
181
+ . unwrap_or_else ( || EffectiveVisibility :: from_vis ( default_vis ( ) ) ) ;
182
+ if let Some ( inherited_effective_vis) = self . get_effective_vis ( parent_id) {
183
+ for level in AccessLevel :: all_levels ( ) {
184
+ if tag >= level {
185
+ let inherited_effective_vis_at_level = * inherited_effective_vis. get ( level) ;
186
+ let calculated_effective_vis =
187
+ if nominal_vis. is_at_least ( inherited_effective_vis_at_level, tree) {
188
+ inherited_effective_vis_at_level
189
+ } else {
190
+ nominal_vis
191
+ } ;
192
+ changed |= current_effective_vis. update ( calculated_effective_vis, level, tree) ;
193
+ }
194
+ }
195
+ } else {
196
+ if !id. into ( ) . is_crate_root ( ) {
197
+ return Err ( ( ) ) ;
198
+ }
199
+ changed |= current_effective_vis. update ( Visibility :: Public , AccessLevel :: Public , tree) ;
200
+ }
201
+ self . map . insert ( id, current_effective_vis) ;
202
+ Ok ( changed)
203
+ }
132
204
}
133
205
134
206
impl < Id > Default for AccessLevels < Id > {
0 commit comments