From cf456d72dbdc44dfde9b79b632ee952ea161d5c4 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 23 Feb 2021 14:54:01 +0100 Subject: [PATCH 1/2] Add test --- crates/ide_completion/src/completions/dot.rs | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs index 0880a38304e..084d7721d73 100644 --- a/crates/ide_completion/src/completions/dot.rs +++ b/crates/ide_completion/src/completions/dot.rs @@ -428,4 +428,32 @@ impl S { fn foo(&self) {} } "#]], ) } + + #[test] + fn completes_after_macro_call_in_submodule() { + check( + r#" +macro_rules! empty { + () => {}; +} + +mod foo { + #[derive(Debug, Default)] + struct Template2 {} + + impl Template2 { + fn private(&self) {} + } + fn baz() { + let goo: Template2 = Template2 {}; + empty!(); + goo.$0 + } +} + "#, + expect![[r#" + me private() -> () + "#]], + ); + } } From 338823f73aefbf7957b928ad76fc5f55cc43df9c Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 23 Feb 2021 17:56:16 +0100 Subject: [PATCH 2/2] is_visible_from_def_map: handle block expressions --- crates/hir_def/src/nameres.rs | 6 +++++ crates/hir_def/src/nameres/collector.rs | 4 +-- crates/hir_def/src/visibility.rs | 36 ++++++++++++++++++++----- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 34ff07f3c4d..f92232eb32d 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -337,6 +337,12 @@ pub fn with_ancestor_maps( None } + /// If this `DefMap` is for a block expression, returns the module containing the block (which + /// might again be a block, or a module inside a block). + pub fn parent(&self) -> Option { + Some(self.block?.parent) + } + // FIXME: this can use some more human-readable format (ideally, an IR // even), as this should be a great debugging aid. pub fn dump(&self, db: &dyn DefDatabase) -> String { diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6bd41bc0821..9996a080721 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -608,7 +608,7 @@ fn record_resolved_import(&mut self, directive: &ImportDirective) { ( n, res.filter_visibility(|v| { - v.is_visible_from_def_map(&self.def_map, module_id) + v.is_visible_from_def_map(self.db, &self.def_map, module_id) }), ) }) @@ -761,7 +761,7 @@ fn update_recursive( .filter(|(glob_importing_module, _)| { // we know all resolutions have the same visibility (`vis`), so we // just need to check that once - vis.is_visible_from_def_map(&self.def_map, *glob_importing_module) + vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module) }) .cloned() .collect::>(); diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 38da3132bf7..0e39519100f 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs @@ -103,7 +103,7 @@ pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> boo return false; } let def_map = from_module.def_map(db); - self.is_visible_from_def_map(&def_map, from_module.local_id) + self.is_visible_from_def_map(db, &def_map, from_module.local_id) } pub(crate) fn is_visible_from_other_crate(self) -> bool { @@ -115,19 +115,41 @@ pub(crate) fn is_visible_from_other_crate(self) -> bool { pub(crate) fn is_visible_from_def_map( self, + db: &dyn DefDatabase, def_map: &DefMap, - from_module: crate::LocalModuleId, + mut from_module: crate::LocalModuleId, ) -> bool { let to_module = match self { Visibility::Module(m) => m, Visibility::Public => return true, }; + // from_module needs to be a descendant of to_module - let mut ancestors = std::iter::successors(Some(from_module), |m| { - let parent_id = def_map[*m].parent?; - Some(parent_id) - }); - ancestors.any(|m| m == to_module.local_id) + let mut def_map = def_map; + let mut parent_arc; + loop { + if def_map.module_id(from_module) == to_module { + return true; + } + match def_map[from_module].parent { + Some(parent) => { + from_module = parent; + } + None => { + match def_map.parent() { + Some(module) => { + parent_arc = module.def_map(db); + def_map = &*parent_arc; + from_module = module.local_id; + } + None => { + // Reached the root module, nothing left to check. + return false; + } + } + } + } + } } /// Returns the most permissive visibility of `self` and `other`.