aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-02-23 16:56:16 +0000
committerJonas Schievink <[email protected]>2021-02-23 16:56:16 +0000
commit338823f73aefbf7957b928ad76fc5f55cc43df9c (patch)
tree94c3b47b3c8c3bdeb7b52c81825907a33134b67d
parentcf456d72dbdc44dfde9b79b632ee952ea161d5c4 (diff)
is_visible_from_def_map: handle block expressions
-rw-r--r--crates/hir_def/src/nameres.rs6
-rw-r--r--crates/hir_def/src/nameres/collector.rs4
-rw-r--r--crates/hir_def/src/visibility.rs36
3 files changed, 37 insertions, 9 deletions
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 34ff07f3c..f92232eb3 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -337,6 +337,12 @@ impl DefMap {
337 None 337 None
338 } 338 }
339 339
340 /// If this `DefMap` is for a block expression, returns the module containing the block (which
341 /// might again be a block, or a module inside a block).
342 pub fn parent(&self) -> Option<ModuleId> {
343 Some(self.block?.parent)
344 }
345
340 // FIXME: this can use some more human-readable format (ideally, an IR 346 // FIXME: this can use some more human-readable format (ideally, an IR
341 // even), as this should be a great debugging aid. 347 // even), as this should be a great debugging aid.
342 pub fn dump(&self, db: &dyn DefDatabase) -> String { 348 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 6bd41bc08..9996a0807 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -608,7 +608,7 @@ impl DefCollector<'_> {
608 ( 608 (
609 n, 609 n,
610 res.filter_visibility(|v| { 610 res.filter_visibility(|v| {
611 v.is_visible_from_def_map(&self.def_map, module_id) 611 v.is_visible_from_def_map(self.db, &self.def_map, module_id)
612 }), 612 }),
613 ) 613 )
614 }) 614 })
@@ -761,7 +761,7 @@ impl DefCollector<'_> {
761 .filter(|(glob_importing_module, _)| { 761 .filter(|(glob_importing_module, _)| {
762 // we know all resolutions have the same visibility (`vis`), so we 762 // we know all resolutions have the same visibility (`vis`), so we
763 // just need to check that once 763 // just need to check that once
764 vis.is_visible_from_def_map(&self.def_map, *glob_importing_module) 764 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
765 }) 765 })
766 .cloned() 766 .cloned()
767 .collect::<Vec<_>>(); 767 .collect::<Vec<_>>();
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs
index 38da3132b..0e3951910 100644
--- a/crates/hir_def/src/visibility.rs
+++ b/crates/hir_def/src/visibility.rs
@@ -103,7 +103,7 @@ impl Visibility {
103 return false; 103 return false;
104 } 104 }
105 let def_map = from_module.def_map(db); 105 let def_map = from_module.def_map(db);
106 self.is_visible_from_def_map(&def_map, from_module.local_id) 106 self.is_visible_from_def_map(db, &def_map, from_module.local_id)
107 } 107 }
108 108
109 pub(crate) fn is_visible_from_other_crate(self) -> bool { 109 pub(crate) fn is_visible_from_other_crate(self) -> bool {
@@ -115,19 +115,41 @@ impl Visibility {
115 115
116 pub(crate) fn is_visible_from_def_map( 116 pub(crate) fn is_visible_from_def_map(
117 self, 117 self,
118 db: &dyn DefDatabase,
118 def_map: &DefMap, 119 def_map: &DefMap,
119 from_module: crate::LocalModuleId, 120 mut from_module: crate::LocalModuleId,
120 ) -> bool { 121 ) -> bool {
121 let to_module = match self { 122 let to_module = match self {
122 Visibility::Module(m) => m, 123 Visibility::Module(m) => m,
123 Visibility::Public => return true, 124 Visibility::Public => return true,
124 }; 125 };
126
125 // from_module needs to be a descendant of to_module 127 // from_module needs to be a descendant of to_module
126 let mut ancestors = std::iter::successors(Some(from_module), |m| { 128 let mut def_map = def_map;
127 let parent_id = def_map[*m].parent?; 129 let mut parent_arc;
128 Some(parent_id) 130 loop {
129 }); 131 if def_map.module_id(from_module) == to_module {
130 ancestors.any(|m| m == to_module.local_id) 132 return true;
133 }
134 match def_map[from_module].parent {
135 Some(parent) => {
136 from_module = parent;
137 }
138 None => {
139 match def_map.parent() {
140 Some(module) => {
141 parent_arc = module.def_map(db);
142 def_map = &*parent_arc;
143 from_module = module.local_id;
144 }
145 None => {
146 // Reached the root module, nothing left to check.
147 return false;
148 }
149 }
150 }
151 }
152 }
131 } 153 }
132 154
133 /// Returns the most permissive visibility of `self` and `other`. 155 /// Returns the most permissive visibility of `self` and `other`.