11//! A pass that checks to make sure private fields and methods aren't used
22//! outside their scopes. This pass will also generate a set of exported items
33//! which are available for use externally when compiled as a library.
4-
4+ use crate :: ty :: Visibility ;
55use rustc_data_structures:: fx:: FxHashMap ;
66use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
77use rustc_macros:: HashStable ;
@@ -27,26 +27,107 @@ pub enum AccessLevel {
2727 Public ,
2828}
2929
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+
3063/// Holds a map of accessibility levels for reachable HIR nodes.
3164#[ derive( Debug , Clone ) ]
3265pub struct AccessLevels < Id = LocalDefId > {
33- pub map : FxHashMap < Id , AccessLevel > ,
66+ map : FxHashMap < Id , EffectiveVisibility > ,
3467}
3568
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+
3775 /// See `AccessLevel::Reachable`.
3876 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 )
4078 }
4179
4280 /// See `AccessLevel::Exported`.
4381 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 )
4583 }
4684
4785 /// See `AccessLevel::Public`.
4886 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 ( ) }
50131 }
51132}
52133
0 commit comments