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
-
4
+ use crate :: ty :: 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 ;
@@ -27,26 +27,107 @@ pub enum AccessLevel {
27
27
Public ,
28
28
}
29
29
30
+ #[ derive( Clone , Copy , PartialEq , Eq , Debug , HashStable , Default ) ]
31
+ pub struct EffectiveVisibility {
32
+ public : Option < Visibility > ,
33
+ exported : Option < Visibility > ,
34
+ reachable : Option < Visibility > ,
35
+ reachable_from_impl_trait : Option < Visibility > ,
36
+ }
37
+
38
+ impl EffectiveVisibility {
39
+ pub fn get ( & self , tag : AccessLevel ) -> Option < & Visibility > {
40
+ match tag {
41
+ AccessLevel :: Public => & self . public ,
42
+ AccessLevel :: Exported => & self . exported ,
43
+ AccessLevel :: Reachable => & self . reachable ,
44
+ AccessLevel :: ReachableFromImplTrait => & self . reachable_from_impl_trait ,
45
+ }
46
+ . as_ref ( )
47
+ }
48
+
49
+ fn get_mut ( & mut self , tag : AccessLevel ) -> & mut Option < Visibility > {
50
+ match tag {
51
+ AccessLevel :: Public => & mut self . public ,
52
+ AccessLevel :: Exported => & mut self . exported ,
53
+ AccessLevel :: Reachable => & mut self . reachable ,
54
+ AccessLevel :: ReachableFromImplTrait => & mut self . reachable_from_impl_trait ,
55
+ }
56
+ }
57
+
58
+ pub fn is_public_at_level ( & self , tag : AccessLevel ) -> bool {
59
+ self . get ( tag) . map_or ( false , |vis| vis. is_public ( ) )
60
+ }
61
+ }
62
+
30
63
/// Holds a map of accessibility levels for reachable HIR nodes.
31
64
#[ derive( Debug , Clone ) ]
32
65
pub struct AccessLevels < Id = LocalDefId > {
33
- pub map : FxHashMap < Id , AccessLevel > ,
66
+ map : FxHashMap < Id , EffectiveVisibility > ,
34
67
}
35
68
36
- impl < Id : Hash + Eq > AccessLevels < Id > {
69
+ impl < Id : Hash + Eq + Copy > AccessLevels < Id > {
70
+ pub fn is_public_at_level ( & self , id : Id , tag : AccessLevel ) -> bool {
71
+ self . get_effective_vis ( id)
72
+ . map_or ( false , |effective_vis| effective_vis. is_public_at_level ( tag) )
73
+ }
74
+
37
75
/// See `AccessLevel::Reachable`.
38
76
pub fn is_reachable ( & self , id : Id ) -> bool {
39
- self . map . get ( & id ) >= Some ( & AccessLevel :: Reachable )
77
+ self . is_public_at_level ( id , AccessLevel :: Reachable )
40
78
}
41
79
42
80
/// See `AccessLevel::Exported`.
43
81
pub fn is_exported ( & self , id : Id ) -> bool {
44
- self . map . get ( & id ) >= Some ( & AccessLevel :: Exported )
82
+ self . is_public_at_level ( id , AccessLevel :: Exported )
45
83
}
46
84
47
85
/// See `AccessLevel::Public`.
48
86
pub fn is_public ( & self , id : Id ) -> bool {
49
- self . map . get ( & id) >= Some ( & AccessLevel :: Public )
87
+ self . is_public_at_level ( id, AccessLevel :: Public )
88
+ }
89
+
90
+ pub fn get_access_level ( & self , id : Id ) -> Option < AccessLevel > {
91
+ 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
+ ] {
98
+ if effective_vis. is_public_at_level ( level) {
99
+ return Some ( level) ;
100
+ }
101
+ }
102
+ None
103
+ } )
104
+ }
105
+
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
+ pub fn get_effective_vis ( & self , id : Id ) -> Option < & EffectiveVisibility > {
122
+ self . map . get ( & id)
123
+ }
124
+
125
+ pub fn iter ( & self ) -> impl Iterator < Item = ( & Id , & EffectiveVisibility ) > {
126
+ self . map . iter ( )
127
+ }
128
+
129
+ pub fn map_id < OutId : Hash + Eq + Copy > ( & self , f : impl Fn ( Id ) -> OutId ) -> AccessLevels < OutId > {
130
+ AccessLevels { map : self . map . iter ( ) . map ( |( k, v) | ( f ( * k) , * v) ) . collect ( ) }
50
131
}
51
132
}
52
133
0 commit comments