Skip to content

Commit 338823f

Browse files
is_visible_from_def_map: handle block expressions
1 parent cf456d7 commit 338823f

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

crates/hir_def/src/nameres.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,12 @@ impl DefMap {
337337
None
338338
}
339339

340+
/// If this `DefMap` is for a block expression, returns the module containing the block (which
341+
/// might again be a block, or a module inside a block).
342+
pub fn parent(&self) -> Option<ModuleId> {
343+
Some(self.block?.parent)
344+
}
345+
340346
// FIXME: this can use some more human-readable format (ideally, an IR
341347
// even), as this should be a great debugging aid.
342348
pub fn dump(&self, db: &dyn DefDatabase) -> String {

crates/hir_def/src/nameres/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ impl DefCollector<'_> {
608608
(
609609
n,
610610
res.filter_visibility(|v| {
611-
v.is_visible_from_def_map(&self.def_map, module_id)
611+
v.is_visible_from_def_map(self.db, &self.def_map, module_id)
612612
}),
613613
)
614614
})
@@ -761,7 +761,7 @@ impl DefCollector<'_> {
761761
.filter(|(glob_importing_module, _)| {
762762
// we know all resolutions have the same visibility (`vis`), so we
763763
// just need to check that once
764-
vis.is_visible_from_def_map(&self.def_map, *glob_importing_module)
764+
vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
765765
})
766766
.cloned()
767767
.collect::<Vec<_>>();

crates/hir_def/src/visibility.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl Visibility {
103103
return false;
104104
}
105105
let def_map = from_module.def_map(db);
106-
self.is_visible_from_def_map(&def_map, from_module.local_id)
106+
self.is_visible_from_def_map(db, &def_map, from_module.local_id)
107107
}
108108

109109
pub(crate) fn is_visible_from_other_crate(self) -> bool {
@@ -115,19 +115,41 @@ impl Visibility {
115115

116116
pub(crate) fn is_visible_from_def_map(
117117
self,
118+
db: &dyn DefDatabase,
118119
def_map: &DefMap,
119-
from_module: crate::LocalModuleId,
120+
mut from_module: crate::LocalModuleId,
120121
) -> bool {
121122
let to_module = match self {
122123
Visibility::Module(m) => m,
123124
Visibility::Public => return true,
124125
};
126+
125127
// from_module needs to be a descendant of to_module
126-
let mut ancestors = std::iter::successors(Some(from_module), |m| {
127-
let parent_id = def_map[*m].parent?;
128-
Some(parent_id)
129-
});
130-
ancestors.any(|m| m == to_module.local_id)
128+
let mut def_map = def_map;
129+
let mut parent_arc;
130+
loop {
131+
if def_map.module_id(from_module) == to_module {
132+
return true;
133+
}
134+
match def_map[from_module].parent {
135+
Some(parent) => {
136+
from_module = parent;
137+
}
138+
None => {
139+
match def_map.parent() {
140+
Some(module) => {
141+
parent_arc = module.def_map(db);
142+
def_map = &*parent_arc;
143+
from_module = module.local_id;
144+
}
145+
None => {
146+
// Reached the root module, nothing left to check.
147+
return false;
148+
}
149+
}
150+
}
151+
}
152+
}
131153
}
132154

133155
/// Returns the most permissive visibility of `self` and `other`.

0 commit comments

Comments
 (0)