@@ -155,10 +155,6 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
155155 }
156156 }
157157
158- fn cheap_private_vis ( & self , parent_id : ParentId < ' _ > ) -> Option < Visibility > {
159- matches ! ( parent_id, ParentId :: Def ( _) ) . then_some ( self . current_private_vis )
160- }
161-
162158 fn effective_vis_or_private ( & mut self , parent_id : ParentId < ' a > ) -> EffectiveVisibility {
163159 // Private nodes are only added to the table for caching, they could be added or removed at
164160 // any moment without consequences, so we don't set `changed` to true when adding them.
@@ -172,29 +168,53 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
172168 }
173169 }
174170
171+ /// All effective visibilities for a node are larger or equal than private visibility
172+ /// for that node (see `check_invariants` in middle/privacy.rs).
173+ /// So if either parent or nominal visibility is the same as private visibility, then
174+ /// `min(parent_vis, nominal_vis) <= private_vis`, and the update logic is guaranteed
175+ /// to not update anything and we can skip it.
176+ ///
177+ /// We are checking this condition only if the correct value of private visibility is
178+ /// cheaply available, otherwise it does't make sense performance-wise.
179+ ///
180+ /// `None` is returned if the update can be skipped,
181+ /// and cheap private visibility is returned otherwise.
182+ fn may_update (
183+ & self ,
184+ nominal_vis : Visibility ,
185+ parent_id : ParentId < ' _ > ,
186+ ) -> Option < Option < Visibility > > {
187+ match parent_id {
188+ ParentId :: Def ( def_id) => ( nominal_vis != self . current_private_vis
189+ && self . r . visibilities [ & def_id] != self . current_private_vis )
190+ . then_some ( Some ( self . current_private_vis ) ) ,
191+ ParentId :: Import ( _) => Some ( None ) ,
192+ }
193+ }
194+
175195 fn update_import ( & mut self , binding : ImportId < ' a > , parent_id : ParentId < ' a > ) {
176196 let nominal_vis = binding. vis . expect_local ( ) ;
177- let private_vis = self . cheap_private_vis ( parent_id) ;
197+ let Some ( cheap_private_vis ) = self . may_update ( nominal_vis , parent_id) else { return } ;
178198 let inherited_eff_vis = self . effective_vis_or_private ( parent_id) ;
179199 let tcx = self . r . tcx ;
180200 self . changed |= self . import_effective_visibilities . update (
181201 binding,
182202 nominal_vis,
183- || private_vis . unwrap_or_else ( || self . r . private_vis_import ( binding) ) ,
203+ || cheap_private_vis . unwrap_or_else ( || self . r . private_vis_import ( binding) ) ,
184204 inherited_eff_vis,
185205 parent_id. level ( ) ,
186206 tcx,
187207 ) ;
188208 }
189209
190210 fn update_def ( & mut self , def_id : LocalDefId , nominal_vis : Visibility , parent_id : ParentId < ' a > ) {
191- let private_vis = self . cheap_private_vis ( parent_id) ;
211+ let Some ( cheap_private_vis ) = self . may_update ( nominal_vis , parent_id) else { return } ;
192212 let inherited_eff_vis = self . effective_vis_or_private ( parent_id) ;
193213 let tcx = self . r . tcx ;
194214 self . changed |= self . def_effective_visibilities . update (
195215 def_id,
196216 nominal_vis,
197- || private_vis . unwrap_or_else ( || self . r . private_vis_def ( def_id) ) ,
217+ || cheap_private_vis . unwrap_or_else ( || self . r . private_vis_def ( def_id) ) ,
198218 inherited_eff_vis,
199219 parent_id. level ( ) ,
200220 tcx,
0 commit comments