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,
/// Declared visibility of this module.
pub visibility: Visibility,
/// Always [`None`] for block modules
pub parent: Option<LocalModuleId>,
pub children: FxHashMap<Name, LocalModuleId>,
pub scope: ItemScope,
@ -429,7 +429,7 @@ impl DefMap {
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.
pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
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
// 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.
// 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.
let arc;
let to_module_def_map =
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
cov_mark::hit!(is_visible_from_same_block_def_map);
def_map
} else {
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();
if is_block_root {
to_module = to_module_def_map.containing_module(to_module.local_id).unwrap();
let mut arc;
loop {
let to_module_def_map =
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
cov_mark::hit!(is_visible_from_same_block_def_map);
def_map
} else {
arc = to_module.def_map(db);
&arc
};
match to_module_def_map.parent() {
Some(parent) => to_module = parent,
None => break,
}
}
// from_module needs to be a descendant of to_module

View file

@ -62,6 +62,26 @@ mod module {
fn main(s: module::Struct) {
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;
}
"#,
);
}