Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #14349 - Veykril:vis-res, r=Veykril
fix: Fix visibility resolution not respecting parent blocks Fixes https://github.com/rust-lang/rust-analyzer/issues/14047
bors 2023-03-14
parent 6f297b9 · parent 1a9fbf0 · commit 74303a3
-rw-r--r--crates/hir-def/src/nameres.rs4
-rw-r--r--crates/hir-def/src/visibility.rs28
-rw-r--r--crates/ide-diagnostics/src/handlers/private_field.rs20
3 files changed, 37 insertions, 15 deletions
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index a7ce036051..59b52c3caa 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -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 {
diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs
index c9fcaae56c..ab76ed43d3 100644
--- a/crates/hir-def/src/visibility.rs
+++ b/crates/hir-def/src/visibility.rs
@@ -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
diff --git a/crates/ide-diagnostics/src/handlers/private_field.rs b/crates/ide-diagnostics/src/handlers/private_field.rs
index e630ae3686..be83ad6aaa 100644
--- a/crates/ide-diagnostics/src/handlers/private_field.rs
+++ b/crates/ide-diagnostics/src/handlers/private_field.rs
@@ -65,4 +65,24 @@ fn main(s: module::Struct) {
"#,
);
}
+
+ #[test]
+ fn block_module_madness() {
+ check_diagnostics(
+ r#"
+fn main() {
+ let strukt = {
+ use crate as ForceParentBlockDefMap;
+ {
+ pub struct Struct {
+ field: (),
+ }
+ Struct { field: () }
+ }
+ };
+ strukt.field;
+}
+"#,
+ );
+ }
}