Skip to content

Commit 3f20f4a

Browse files
committed
effective visibility: Satisfy borrow checker to use resolver lazily from a closure
1 parent d121aa3 commit 3f20f4a

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

compiler/rustc_middle/src/middle/privacy.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,13 @@ impl EffectiveVisibilities {
142142
pub fn set_public_at_level(
143143
&mut self,
144144
id: LocalDefId,
145-
default_vis: impl FnOnce() -> Visibility,
145+
lazy_private_vis: impl FnOnce() -> Visibility,
146146
level: Level,
147147
) {
148148
let mut effective_vis = self
149149
.effective_vis(id)
150150
.copied()
151-
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
151+
.unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
152152
for l in Level::all_levels() {
153153
if l <= level {
154154
*effective_vis.at_level_mut(l) = Visibility::Public;
@@ -206,6 +206,11 @@ impl EffectiveVisibilities {
206206
}
207207
}
208208

209+
pub trait IntoDefIdTree {
210+
type Tree: DefIdTree;
211+
fn tree(self) -> Self::Tree;
212+
}
213+
209214
impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
210215
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
211216
self.map.iter()
@@ -217,21 +222,26 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
217222

218223
// `parent_id` is not necessarily a parent in source code tree,
219224
// it is the node from which the maximum effective visibility is inherited.
220-
pub fn update(
225+
pub fn update<T: IntoDefIdTree>(
221226
&mut self,
222227
id: Id,
223228
nominal_vis: Visibility,
224-
default_vis: Visibility,
229+
lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
225230
inherited_eff_vis: Option<EffectiveVisibility>,
226231
level: Level,
227-
tree: impl DefIdTree,
232+
mut into_tree: T,
228233
) -> bool {
229234
let mut changed = false;
230-
let mut current_effective_vis = self
231-
.map
232-
.get(&id)
233-
.copied()
234-
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis));
235+
let mut current_effective_vis = match self.map.get(&id).copied() {
236+
Some(eff_vis) => eff_vis,
237+
None => {
238+
let private_vis;
239+
(private_vis, into_tree) = lazy_private_vis(into_tree);
240+
EffectiveVisibility::from_vis(private_vis)
241+
}
242+
};
243+
let tree = into_tree.tree();
244+
235245
if let Some(inherited_effective_vis) = inherited_eff_vis {
236246
let mut inherited_effective_vis_at_prev_level =
237247
*inherited_effective_vis.at_level(level);

compiler/rustc_resolve/src/effective_visibilities.rs

+26-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use rustc_ast::EnumDef;
77
use rustc_data_structures::intern::Interned;
88
use rustc_hir::def_id::LocalDefId;
99
use rustc_hir::def_id::CRATE_DEF_ID;
10-
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
10+
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
11+
use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
1112
use rustc_middle::ty::Visibility;
1213

1314
type ImportId<'a> = Interned<'a, NameBinding<'a>>;
@@ -29,20 +30,35 @@ impl ParentId<'_> {
2930

3031
pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
3132
r: &'r mut Resolver<'a>,
33+
def_effective_visibilities: EffectiveVisibilities,
3234
/// While walking import chains we need to track effective visibilities per-binding, and def id
3335
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
3436
/// bindings can correspond to a single def id in imports. So we keep a separate table.
3537
import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>,
3638
changed: bool,
3739
}
3840

41+
impl Resolver<'_> {
42+
fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
43+
self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
44+
}
45+
}
46+
47+
impl<'a, 'b> IntoDefIdTree for &'b mut Resolver<'a> {
48+
type Tree = &'b Resolver<'a>;
49+
fn tree(self) -> Self::Tree {
50+
self
51+
}
52+
}
53+
3954
impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
4055
/// Fills the `Resolver::effective_visibilities` table with public & exported items
4156
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
4257
/// need access to a TyCtxt for that.
4358
pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
4459
let mut visitor = EffectiveVisibilitiesVisitor {
4560
r,
61+
def_effective_visibilities: Default::default(),
4662
import_effective_visibilities: Default::default(),
4763
changed: false,
4864
};
@@ -54,6 +70,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
5470
visitor.changed = false;
5571
visit::walk_crate(&mut visitor, krate);
5672
}
73+
visitor.r.effective_visibilities = visitor.def_effective_visibilities;
5774

5875
// Update visibilities for import def ids. These are not used during the
5976
// `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
@@ -90,10 +107,6 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
90107
info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
91108
}
92109

93-
fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
94-
self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
95-
}
96-
97110
/// Update effective visibilities of bindings in the given module,
98111
/// including their whole reexport chains.
99112
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
@@ -124,7 +137,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
124137

125138
fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
126139
match parent_id {
127-
ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id),
140+
ParentId::Def(def_id) => self.def_effective_visibilities.effective_vis(def_id),
128141
ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
129142
}
130143
.copied()
@@ -150,7 +163,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
150163
let default_vis = Visibility::Restricted(
151164
import
152165
.id()
153-
.map(|id| self.nearest_normal_mod(self.r.local_def_id(id)))
166+
.map(|id| self.r.nearest_normal_mod(self.r.local_def_id(id)))
154167
.unwrap_or(CRATE_DEF_ID),
155168
);
156169
if self.is_noop_update(parent_id, nominal_vis, default_vis) {
@@ -159,25 +172,25 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
159172
self.changed |= self.import_effective_visibilities.update(
160173
binding,
161174
nominal_vis,
162-
default_vis,
175+
|r| (default_vis, r),
163176
self.effective_vis(parent_id),
164177
parent_id.level(),
165-
ResolverTree(&self.r.definitions, &self.r.crate_loader),
178+
&mut *self.r,
166179
);
167180
}
168181

169182
fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
170-
let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id));
183+
let default_vis = Visibility::Restricted(self.r.nearest_normal_mod(def_id));
171184
if self.is_noop_update(parent_id, nominal_vis, default_vis) {
172185
return;
173186
}
174-
self.changed |= self.r.effective_visibilities.update(
187+
self.changed |= self.def_effective_visibilities.update(
175188
def_id,
176189
nominal_vis,
177-
if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis },
190+
|r| (if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis }, r),
178191
self.effective_vis(parent_id),
179192
parent_id.level(),
180-
ResolverTree(&self.r.definitions, &self.r.crate_loader),
193+
&mut *self.r,
181194
);
182195
}
183196

0 commit comments

Comments
 (0)