Skip to content

Commit 7e76d94

Browse files
committed
effective visibility: Always add table entries for nodes used as parents
Previously if the parent was not in the table, and there was nothing to inherit from, the child's private visibility was used, but that's not correct - the parent may have a larger visibility so we should set it to at least the parent's private visibility. That parent's private visibility is also inserted into the table for caching, so it's not recalculated later if used again.
1 parent a45a302 commit 7e76d94

File tree

2 files changed

+51
-40
lines changed

2 files changed

+51
-40
lines changed

compiler/rustc_middle/src/middle/privacy.rs

+37-33
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,21 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
213213
self.map.get(&id)
214214
}
215215

216-
// `parent_id` is not necessarily a parent in source code tree,
217-
// it is the node from which the maximum effective visibility is inherited.
216+
// FIXME: Share code with `fn update`.
217+
pub fn effective_vis_or_private(
218+
&mut self,
219+
id: Id,
220+
lazy_private_vis: impl FnOnce() -> Visibility,
221+
) -> &EffectiveVisibility {
222+
self.map.entry(id).or_insert_with(|| EffectiveVisibility::from_vis(lazy_private_vis()))
223+
}
224+
218225
pub fn update<T: IntoDefIdTree>(
219226
&mut self,
220227
id: Id,
221228
nominal_vis: Visibility,
222229
lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
223-
inherited_eff_vis: Option<EffectiveVisibility>,
230+
inherited_effective_vis: EffectiveVisibility,
224231
level: Level,
225232
mut into_tree: T,
226233
) -> bool {
@@ -235,39 +242,36 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
235242
};
236243
let tree = into_tree.tree();
237244

238-
if let Some(inherited_effective_vis) = inherited_eff_vis {
239-
let mut inherited_effective_vis_at_prev_level =
240-
*inherited_effective_vis.at_level(level);
241-
let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
242-
for l in Level::all_levels() {
243-
if level >= l {
244-
let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l);
245-
let current_effective_vis_at_level = current_effective_vis.at_level_mut(l);
246-
// effective visibility for id shouldn't be recalculated if
247-
// inherited from parent_id effective visibility isn't changed at next level
248-
if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
249-
&& level != l)
250-
{
251-
calculated_effective_vis =
252-
if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
253-
inherited_effective_vis_at_level
254-
} else {
255-
nominal_vis
256-
};
257-
}
258-
// effective visibility can't be decreased at next update call for the
259-
// same id
260-
if *current_effective_vis_at_level != calculated_effective_vis
261-
&& calculated_effective_vis
262-
.is_at_least(*current_effective_vis_at_level, tree)
263-
{
264-
changed = true;
265-
*current_effective_vis_at_level = calculated_effective_vis;
266-
}
267-
inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level;
245+
let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level);
246+
let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
247+
for l in Level::all_levels() {
248+
if level >= l {
249+
let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l);
250+
let current_effective_vis_at_level = current_effective_vis.at_level_mut(l);
251+
// effective visibility for id shouldn't be recalculated if
252+
// inherited from parent_id effective visibility isn't changed at next level
253+
if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
254+
&& level != l)
255+
{
256+
calculated_effective_vis =
257+
if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
258+
inherited_effective_vis_at_level
259+
} else {
260+
nominal_vis
261+
};
262+
}
263+
// effective visibility can't be decreased at next update call for the
264+
// same id
265+
if *current_effective_vis_at_level != calculated_effective_vis
266+
&& calculated_effective_vis.is_at_least(*current_effective_vis_at_level, tree)
267+
{
268+
changed = true;
269+
*current_effective_vis_at_level = calculated_effective_vis;
268270
}
271+
inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level;
269272
}
270273
}
274+
271275
self.map.insert(id, current_effective_vis);
272276
changed
273277
}

compiler/rustc_resolve/src/effective_visibilities.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -155,32 +155,39 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
155155
}
156156
}
157157

158-
fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
159-
match parent_id {
160-
ParentId::Def(def_id) => self.def_effective_visibilities.effective_vis(def_id),
161-
ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
158+
fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility {
159+
// Private nodes are only added to the table for caching, they could be added or removed at
160+
// any moment without consequences, so we don't set `changed` to true when adding them.
161+
*match parent_id {
162+
ParentId::Def(def_id) => self
163+
.def_effective_visibilities
164+
.effective_vis_or_private(def_id, || self.r.private_vis_def(def_id)),
165+
ParentId::Import(binding) => self
166+
.import_effective_visibilities
167+
.effective_vis_or_private(binding, || self.r.private_vis_import(binding)),
162168
}
163-
.copied()
164169
}
165170

166171
fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
167172
let nominal_vis = binding.vis.expect_local();
173+
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
168174
self.changed |= self.import_effective_visibilities.update(
169175
binding,
170176
nominal_vis,
171177
|r| (r.private_vis_import(binding), r),
172-
self.effective_vis(parent_id),
178+
inherited_eff_vis,
173179
parent_id.level(),
174180
&mut *self.r,
175181
);
176182
}
177183

178184
fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
185+
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
179186
self.changed |= self.def_effective_visibilities.update(
180187
def_id,
181188
nominal_vis,
182189
|r| (r.private_vis_def(def_id), r),
183-
self.effective_vis(parent_id),
190+
inherited_eff_vis,
184191
parent_id.level(),
185192
&mut *self.r,
186193
);

0 commit comments

Comments
 (0)