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- use crate :: ty:: Visibility ;
4+ use crate :: ty:: { DefIdTree , Visibility } ;
55use rustc_data_structures:: fx:: FxHashMap ;
66use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
77use rustc_macros:: HashStable ;
88use rustc_query_system:: ich:: StableHashingContext ;
9- use rustc_span:: def_id:: LocalDefId ;
9+ use rustc_span:: def_id:: { DefId , LocalDefId } ;
1010use std:: hash:: Hash ;
1111
1212/// Represents the levels of accessibility an item can have.
@@ -27,26 +27,36 @@ pub enum AccessLevel {
2727 Public ,
2828}
2929
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 ) ]
3142pub 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 ,
3647}
3748
3849impl EffectiveVisibility {
39- pub fn get ( & self , tag : AccessLevel ) -> Option < & Visibility > {
50+ pub fn get ( & self , tag : AccessLevel ) -> & Visibility {
4051 match tag {
4152 AccessLevel :: Public => & self . public ,
4253 AccessLevel :: Exported => & self . exported ,
4354 AccessLevel :: Reachable => & self . reachable ,
4455 AccessLevel :: ReachableFromImplTrait => & self . reachable_from_impl_trait ,
4556 }
46- . as_ref ( )
4757 }
4858
49- fn get_mut ( & mut self , tag : AccessLevel ) -> & mut Option < Visibility > {
59+ fn get_mut ( & mut self , tag : AccessLevel ) -> & mut Visibility {
5060 match tag {
5161 AccessLevel :: Public => & mut self . public ,
5262 AccessLevel :: Exported => & mut self . exported ,
@@ -56,7 +66,30 @@ impl EffectiveVisibility {
5666 }
5767
5868 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+ }
6093 }
6194}
6295
@@ -89,12 +122,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
89122
90123 pub fn get_access_level ( & self , id : Id ) -> Option < AccessLevel > {
91124 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 ( ) {
98126 if effective_vis. is_public_at_level ( level) {
99127 return Some ( level) ;
100128 }
@@ -103,21 +131,6 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
103131 } )
104132 }
105133
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-
121134 pub fn get_effective_vis ( & self , id : Id ) -> Option < & EffectiveVisibility > {
122135 self . map . get ( & id)
123136 }
@@ -129,6 +142,65 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
129142 pub fn map_id < OutId : Hash + Eq + Copy > ( & self , f : impl Fn ( Id ) -> OutId ) -> AccessLevels < OutId > {
130143 AccessLevels { map : self . map . iter ( ) . map ( |( k, v) | ( f ( * k) , * v) ) . collect ( ) }
131144 }
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+ }
132204}
133205
134206impl < Id > Default for AccessLevels < Id > {
0 commit comments