@@ -10,6 +10,7 @@ use rustc_hir::def_id::CRATE_DEF_ID;
10
10
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
11
11
use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
12
12
use rustc_middle::ty::{DefIdTree, Visibility};
13
+ use std::mem;
13
14
14
15
type ImportId<'a> = Interned<'a, NameBinding<'a>>;
15
16
@@ -35,6 +36,8 @@ pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
35
36
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
36
37
/// bindings can correspond to a single def id in imports. So we keep a separate table.
37
38
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,
38
41
changed: bool,
39
42
}
40
43
@@ -80,10 +83,12 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
80
83
r,
81
84
def_effective_visibilities: Default::default(),
82
85
import_effective_visibilities: Default::default(),
86
+ current_private_vis: Visibility::Public,
83
87
changed: false,
84
88
};
85
89
86
90
visitor.update(CRATE_DEF_ID, CRATE_DEF_ID);
91
+ visitor.current_private_vis = Visibility::Restricted(CRATE_DEF_ID);
87
92
visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
88
93
89
94
while visitor.changed {
@@ -155,6 +160,10 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
155
160
}
156
161
}
157
162
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
+
158
167
fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility {
159
168
// Private nodes are only added to the table for caching, they could be added or removed at
160
169
// 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> {
170
179
171
180
fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
172
181
let nominal_vis = binding.vis.expect_local();
182
+ let private_vis = self.cheap_private_vis(parent_id);
173
183
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
174
184
self.changed |= self.import_effective_visibilities.update(
175
185
binding,
176
186
nominal_vis,
177
- |r| (r.private_vis_import(binding), r),
187
+ |r| (private_vis.unwrap_or_else(|| r.private_vis_import(binding) ), r),
178
188
inherited_eff_vis,
179
189
parent_id.level(),
180
190
&mut *self.r,
181
191
);
182
192
}
183
193
184
194
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);
185
196
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
186
197
self.changed |= self.def_effective_visibilities.update(
187
198
def_id,
188
199
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),
190
201
inherited_eff_vis,
191
202
parent_id.level(),
192
203
&mut *self.r,
@@ -213,8 +224,11 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
213
224
),
214
225
215
226
ast::ItemKind::Mod(..) => {
227
+ let prev_private_vis =
228
+ mem::replace(&mut self.current_private_vis, Visibility::Restricted(def_id));
216
229
self.set_bindings_effective_visibilities(def_id);
217
230
visit::walk_item(self, item);
231
+ self.current_private_vis = prev_private_vis;
218
232
}
219
233
220
234
ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
0 commit comments