mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 13:33:31 +00:00
fix: Fix visibility resolution not respecting parent blocks
This commit is contained in:
parent
6f297b9076
commit
1a9fbf0a6d
3 changed files with 37 additions and 15 deletions
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue