effective visibility: Satisfy borrow checker to use resolver lazily from a closure
This commit is contained in:
parent
d121aa3b55
commit
3f20f4ac42
2 changed files with 46 additions and 23 deletions
|
@ -142,13 +142,13 @@ impl EffectiveVisibilities {
|
||||||
pub fn set_public_at_level(
|
pub fn set_public_at_level(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: LocalDefId,
|
id: LocalDefId,
|
||||||
default_vis: impl FnOnce() -> Visibility,
|
lazy_private_vis: impl FnOnce() -> Visibility,
|
||||||
level: Level,
|
level: Level,
|
||||||
) {
|
) {
|
||||||
let mut effective_vis = self
|
let mut effective_vis = self
|
||||||
.effective_vis(id)
|
.effective_vis(id)
|
||||||
.copied()
|
.copied()
|
||||||
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
|
.unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
|
||||||
for l in Level::all_levels() {
|
for l in Level::all_levels() {
|
||||||
if l <= level {
|
if l <= level {
|
||||||
*effective_vis.at_level_mut(l) = Visibility::Public;
|
*effective_vis.at_level_mut(l) = Visibility::Public;
|
||||||
|
@ -206,6 +206,11 @@ impl EffectiveVisibilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IntoDefIdTree {
|
||||||
|
type Tree: DefIdTree;
|
||||||
|
fn tree(self) -> Self::Tree;
|
||||||
|
}
|
||||||
|
|
||||||
impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
|
impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
|
||||||
self.map.iter()
|
self.map.iter()
|
||||||
|
@ -217,21 +222,26 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
|
||||||
|
|
||||||
// `parent_id` is not necessarily a parent in source code tree,
|
// `parent_id` is not necessarily a parent in source code tree,
|
||||||
// it is the node from which the maximum effective visibility is inherited.
|
// it is the node from which the maximum effective visibility is inherited.
|
||||||
pub fn update(
|
pub fn update<T: IntoDefIdTree>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: Id,
|
id: Id,
|
||||||
nominal_vis: Visibility,
|
nominal_vis: Visibility,
|
||||||
default_vis: Visibility,
|
lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
|
||||||
inherited_eff_vis: Option<EffectiveVisibility>,
|
inherited_eff_vis: Option<EffectiveVisibility>,
|
||||||
level: Level,
|
level: Level,
|
||||||
tree: impl DefIdTree,
|
mut into_tree: T,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
let mut current_effective_vis = self
|
let mut current_effective_vis = match self.map.get(&id).copied() {
|
||||||
.map
|
Some(eff_vis) => eff_vis,
|
||||||
.get(&id)
|
None => {
|
||||||
.copied()
|
let private_vis;
|
||||||
.unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis));
|
(private_vis, into_tree) = lazy_private_vis(into_tree);
|
||||||
|
EffectiveVisibility::from_vis(private_vis)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tree = into_tree.tree();
|
||||||
|
|
||||||
if let Some(inherited_effective_vis) = inherited_eff_vis {
|
if let Some(inherited_effective_vis) = inherited_eff_vis {
|
||||||
let mut inherited_effective_vis_at_prev_level =
|
let mut inherited_effective_vis_at_prev_level =
|
||||||
*inherited_effective_vis.at_level(level);
|
*inherited_effective_vis.at_level(level);
|
||||||
|
|
|
@ -7,7 +7,8 @@ use rustc_ast::EnumDef;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||||
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
|
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
|
||||||
|
use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
|
||||||
use rustc_middle::ty::Visibility;
|
use rustc_middle::ty::Visibility;
|
||||||
|
|
||||||
type ImportId<'a> = Interned<'a, NameBinding<'a>>;
|
type ImportId<'a> = Interned<'a, NameBinding<'a>>;
|
||||||
|
@ -29,6 +30,7 @@ impl ParentId<'_> {
|
||||||
|
|
||||||
pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
|
pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
r: &'r mut Resolver<'a>,
|
r: &'r mut Resolver<'a>,
|
||||||
|
def_effective_visibilities: EffectiveVisibilities,
|
||||||
/// While walking import chains we need to track effective visibilities per-binding, and def id
|
/// While walking import chains we need to track effective visibilities per-binding, and def id
|
||||||
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
|
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
|
||||||
/// bindings can correspond to a single def id in imports. So we keep a separate table.
|
/// bindings can correspond to a single def id in imports. So we keep a separate table.
|
||||||
|
@ -36,6 +38,19 @@ pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
changed: bool,
|
changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Resolver<'_> {
|
||||||
|
fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
|
||||||
|
self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> IntoDefIdTree for &'b mut Resolver<'a> {
|
||||||
|
type Tree = &'b Resolver<'a>;
|
||||||
|
fn tree(self) -> Self::Tree {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
/// Fills the `Resolver::effective_visibilities` table with public & exported items
|
/// Fills the `Resolver::effective_visibilities` table with public & exported items
|
||||||
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
|
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
|
||||||
|
@ -43,6 +58,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
|
pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
|
||||||
let mut visitor = EffectiveVisibilitiesVisitor {
|
let mut visitor = EffectiveVisibilitiesVisitor {
|
||||||
r,
|
r,
|
||||||
|
def_effective_visibilities: Default::default(),
|
||||||
import_effective_visibilities: Default::default(),
|
import_effective_visibilities: Default::default(),
|
||||||
changed: false,
|
changed: false,
|
||||||
};
|
};
|
||||||
|
@ -54,6 +70,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
visitor.changed = false;
|
visitor.changed = false;
|
||||||
visit::walk_crate(&mut visitor, krate);
|
visit::walk_crate(&mut visitor, krate);
|
||||||
}
|
}
|
||||||
|
visitor.r.effective_visibilities = visitor.def_effective_visibilities;
|
||||||
|
|
||||||
// Update visibilities for import def ids. These are not used during the
|
// Update visibilities for import def ids. These are not used during the
|
||||||
// `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
|
// `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
|
||||||
|
@ -90,10 +107,6 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
|
info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
|
|
||||||
self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update effective visibilities of bindings in the given module,
|
/// Update effective visibilities of bindings in the given module,
|
||||||
/// including their whole reexport chains.
|
/// including their whole reexport chains.
|
||||||
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
|
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
|
||||||
|
@ -124,7 +137,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
|
|
||||||
fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
|
fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
|
||||||
match parent_id {
|
match parent_id {
|
||||||
ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id),
|
ParentId::Def(def_id) => self.def_effective_visibilities.effective_vis(def_id),
|
||||||
ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
|
ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
|
||||||
}
|
}
|
||||||
.copied()
|
.copied()
|
||||||
|
@ -150,7 +163,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
let default_vis = Visibility::Restricted(
|
let default_vis = Visibility::Restricted(
|
||||||
import
|
import
|
||||||
.id()
|
.id()
|
||||||
.map(|id| self.nearest_normal_mod(self.r.local_def_id(id)))
|
.map(|id| self.r.nearest_normal_mod(self.r.local_def_id(id)))
|
||||||
.unwrap_or(CRATE_DEF_ID),
|
.unwrap_or(CRATE_DEF_ID),
|
||||||
);
|
);
|
||||||
if self.is_noop_update(parent_id, nominal_vis, default_vis) {
|
if self.is_noop_update(parent_id, nominal_vis, default_vis) {
|
||||||
|
@ -159,25 +172,25 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||||
self.changed |= self.import_effective_visibilities.update(
|
self.changed |= self.import_effective_visibilities.update(
|
||||||
binding,
|
binding,
|
||||||
nominal_vis,
|
nominal_vis,
|
||||||
default_vis,
|
|r| (default_vis, r),
|
||||||
self.effective_vis(parent_id),
|
self.effective_vis(parent_id),
|
||||||
parent_id.level(),
|
parent_id.level(),
|
||||||
ResolverTree(&self.r.definitions, &self.r.crate_loader),
|
&mut *self.r,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
|
fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
|
||||||
let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id));
|
let default_vis = Visibility::Restricted(self.r.nearest_normal_mod(def_id));
|
||||||
if self.is_noop_update(parent_id, nominal_vis, default_vis) {
|
if self.is_noop_update(parent_id, nominal_vis, default_vis) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.changed |= self.r.effective_visibilities.update(
|
self.changed |= self.def_effective_visibilities.update(
|
||||||
def_id,
|
def_id,
|
||||||
nominal_vis,
|
nominal_vis,
|
||||||
if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis },
|
|r| (if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis }, r),
|
||||||
self.effective_vis(parent_id),
|
self.effective_vis(parent_id),
|
||||||
parent_id.level(),
|
parent_id.level(),
|
||||||
ResolverTree(&self.r.definitions, &self.r.crate_loader),
|
&mut *self.r,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue