is_visible_from_def_map: handle block expressions

This commit is contained in:
Jonas Schievink 2021-02-23 17:56:16 +01:00
parent cf456d72db
commit 338823f73a
3 changed files with 37 additions and 9 deletions

View File

@ -337,6 +337,12 @@ pub fn with_ancestor_maps<T>(
None
}
/// If this `DefMap` is for a block expression, returns the module containing the block (which
/// might again be a block, or a module inside a block).
pub fn parent(&self) -> Option<ModuleId> {
Some(self.block?.parent)
}
// FIXME: this can use some more human-readable format (ideally, an IR
// even), as this should be a great debugging aid.
pub fn dump(&self, db: &dyn DefDatabase) -> String {

View File

@ -608,7 +608,7 @@ fn record_resolved_import(&mut self, directive: &ImportDirective) {
(
n,
res.filter_visibility(|v| {
v.is_visible_from_def_map(&self.def_map, module_id)
v.is_visible_from_def_map(self.db, &self.def_map, module_id)
}),
)
})
@ -761,7 +761,7 @@ fn update_recursive(
.filter(|(glob_importing_module, _)| {
// we know all resolutions have the same visibility (`vis`), so we
// just need to check that once
vis.is_visible_from_def_map(&self.def_map, *glob_importing_module)
vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
})
.cloned()
.collect::<Vec<_>>();

View File

@ -103,7 +103,7 @@ pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> boo
return false;
}
let def_map = from_module.def_map(db);
self.is_visible_from_def_map(&def_map, from_module.local_id)
self.is_visible_from_def_map(db, &def_map, from_module.local_id)
}
pub(crate) fn is_visible_from_other_crate(self) -> bool {
@ -115,19 +115,41 @@ pub(crate) fn is_visible_from_other_crate(self) -> bool {
pub(crate) fn is_visible_from_def_map(
self,
db: &dyn DefDatabase,
def_map: &DefMap,
from_module: crate::LocalModuleId,
mut from_module: crate::LocalModuleId,
) -> bool {
let to_module = match self {
Visibility::Module(m) => m,
Visibility::Public => return true,
};
// from_module needs to be a descendant of to_module
let mut ancestors = std::iter::successors(Some(from_module), |m| {
let parent_id = def_map[*m].parent?;
Some(parent_id)
});
ancestors.any(|m| m == to_module.local_id)
let mut def_map = def_map;
let mut parent_arc;
loop {
if def_map.module_id(from_module) == to_module {
return true;
}
match def_map[from_module].parent {
Some(parent) => {
from_module = parent;
}
None => {
match def_map.parent() {
Some(module) => {
parent_arc = module.def_map(db);
def_map = &*parent_arc;
from_module = module.local_id;
}
None => {
// Reached the root module, nothing left to check.
return false;
}
}
}
}
}
}
/// Returns the most permissive visibility of `self` and `other`.