@@ -10,6 +10,7 @@ use rustc_hir::def_id::CRATE_DEF_ID;
1010use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
1111use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
1212use rustc_middle::ty::{DefIdTree, Visibility};
13+ use std::mem;
1314
1415type ImportId<'a> = Interned<'a, NameBinding<'a>>;
1516
@@ -35,6 +36,8 @@ pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
3536 /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
3637 /// bindings can correspond to a single def id in imports. So we keep a separate table.
3738 import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>,
39+ // It's possible to recalculate this at any point, but it's relatively expensive.
40+ current_private_vis: Visibility,
3841 changed: bool,
3942}
4043
@@ -80,10 +83,12 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
8083 r,
8184 def_effective_visibilities: Default::default(),
8285 import_effective_visibilities: Default::default(),
86+ current_private_vis: Visibility::Public,
8387 changed: false,
8488 };
8589
8690 visitor.update(CRATE_DEF_ID, CRATE_DEF_ID);
91+ visitor.current_private_vis = Visibility::Restricted(CRATE_DEF_ID);
8792 visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
8893
8994 while visitor.changed {
@@ -155,6 +160,10 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
155160 }
156161 }
157162
163+ fn cheap_private_vis(&self, parent_id: ParentId<'_>) -> Option<Visibility> {
164+ matches!(parent_id, ParentId::Def(_)).then_some(self.current_private_vis)
165+ }
166+
158167 fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility {
159168 // Private nodes are only added to the table for caching, they could be added or removed at
160169 // any moment without consequences, so we don't set `changed` to true when adding them.
@@ -170,23 +179,25 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
170179
171180 fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
172181 let nominal_vis = binding.vis.expect_local();
182+ let private_vis = self.cheap_private_vis(parent_id);
173183 let inherited_eff_vis = self.effective_vis_or_private(parent_id);
174184 self.changed |= self.import_effective_visibilities.update(
175185 binding,
176186 nominal_vis,
177- |r| (r.private_vis_import(binding), r),
187+ |r| (private_vis.unwrap_or_else(|| r.private_vis_import(binding) ), r),
178188 inherited_eff_vis,
179189 parent_id.level(),
180190 &mut *self.r,
181191 );
182192 }
183193
184194 fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
195+ let private_vis = self.cheap_private_vis(parent_id);
185196 let inherited_eff_vis = self.effective_vis_or_private(parent_id);
186197 self.changed |= self.def_effective_visibilities.update(
187198 def_id,
188199 nominal_vis,
189- |r| (r.private_vis_def(def_id), r),
200+ |r| (private_vis.unwrap_or_else(|| r.private_vis_def(def_id) ), r),
190201 inherited_eff_vis,
191202 parent_id.level(),
192203 &mut *self.r,
@@ -213,8 +224,11 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
213224 ),
214225
215226 ast::ItemKind::Mod(..) => {
227+ let prev_private_vis =
228+ mem::replace(&mut self.current_private_vis, Visibility::Restricted(def_id));
216229 self.set_bindings_effective_visibilities(def_id);
217230 visit::walk_item(self, item);
231+ self.current_private_vis = prev_private_vis;
218232 }
219233
220234 ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
0 commit comments