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 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 // FIXME: this can use some more human-readable format (ideally, an IR
// even), as this should be a great debugging aid. // even), as this should be a great debugging aid.
pub fn dump(&self, db: &dyn DefDatabase) -> String { pub fn dump(&self, db: &dyn DefDatabase) -> String {

View File

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

View File

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