fix: Fix visibility resolution not respecting parent blocks

This commit is contained in:
Lukas Wirth 2023-03-14 13:42:08 +01:00
parent 6f297b9076
commit 1a9fbf0a6d
3 changed files with 37 additions and 15 deletions

View file

@ -215,7 +215,7 @@ pub struct ModuleData {
pub origin: ModuleOrigin, pub origin: ModuleOrigin,
/// Declared visibility of this module. /// Declared visibility of this module.
pub visibility: Visibility, pub visibility: Visibility,
/// Always [`None`] for block modules
pub parent: Option<LocalModuleId>, pub parent: Option<LocalModuleId>,
pub children: FxHashMap<Name, LocalModuleId>, pub children: FxHashMap<Name, LocalModuleId>,
pub scope: ItemScope, pub scope: ItemScope,
@ -429,7 +429,7 @@ impl DefMap {
Some(self.block?.parent) Some(self.block?.parent)
} }
/// Returns the module containing `local_mod`, either the parent `mod`, or the module containing /// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
/// the block, if `self` corresponds to a block expression. /// the block, if `self` corresponds to a block expression.
pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> { pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
match self[local_mod].parent { match self[local_mod].parent {

View file

@ -131,21 +131,23 @@ impl Visibility {
// visibility as the containing module (even though no items are directly nameable from // visibility as the containing module (even though no items are directly nameable from
// there, getting this right is important for method resolution). // there, getting this right is important for method resolution).
// In that case, we adjust the visibility of `to_module` to point to the containing module. // In that case, we adjust the visibility of `to_module` to point to the containing module.
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're // Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
// currently computing, so we must not call the `def_map` query for it. // currently computing, so we must not call the `def_map` query for it.
let arc; let mut arc;
let to_module_def_map = loop {
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() { let to_module_def_map =
cov_mark::hit!(is_visible_from_same_block_def_map); if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
def_map cov_mark::hit!(is_visible_from_same_block_def_map);
} else { def_map
arc = to_module.def_map(db); } else {
&arc arc = to_module.def_map(db);
}; &arc
let is_block_root = };
to_module.block.is_some() && to_module_def_map[to_module.local_id].parent.is_none(); match to_module_def_map.parent() {
if is_block_root { Some(parent) => to_module = parent,
to_module = to_module_def_map.containing_module(to_module.local_id).unwrap(); None => break,
}
} }
// from_module needs to be a descendant of to_module // from_module needs to be a descendant of to_module

View file

@ -62,6 +62,26 @@ mod module {
fn main(s: module::Struct) { fn main(s: module::Struct) {
s.field; s.field;
} }
"#,
);
}
#[test]
fn block_module_madness() {
check_diagnostics(
r#"
fn main() {
let strukt = {
use crate as ForceParentBlockDefMap;
{
pub struct Struct {
field: (),
}
Struct { field: () }
}
};
strukt.field;
}
"#, "#,
); );
} }