diff options
Diffstat (limited to 'crates/hir_def/src/visibility.rs')
-rw-r--r-- | crates/hir_def/src/visibility.rs | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index f3bc9d680..0e3951910 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -5,7 +5,7 @@ use syntax::ast; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | nameres::CrateDefMap, | 8 | nameres::DefMap, |
9 | path::{ModPath, PathKind}, | 9 | path::{ModPath, PathKind}, |
10 | ModuleId, | 10 | ModuleId, |
11 | }; | 11 | }; |
@@ -22,8 +22,7 @@ pub enum RawVisibility { | |||
22 | 22 | ||
23 | impl RawVisibility { | 23 | impl RawVisibility { |
24 | pub(crate) const fn private() -> RawVisibility { | 24 | pub(crate) const fn private() -> RawVisibility { |
25 | let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() }; | 25 | RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) |
26 | RawVisibility::Module(path) | ||
27 | } | 26 | } |
28 | 27 | ||
29 | pub(crate) fn from_ast( | 28 | pub(crate) fn from_ast( |
@@ -59,15 +58,15 @@ impl RawVisibility { | |||
59 | RawVisibility::Module(path) | 58 | RawVisibility::Module(path) |
60 | } | 59 | } |
61 | ast::VisibilityKind::PubCrate => { | 60 | ast::VisibilityKind::PubCrate => { |
62 | let path = ModPath { kind: PathKind::Crate, segments: Vec::new() }; | 61 | let path = ModPath::from_kind(PathKind::Crate); |
63 | RawVisibility::Module(path) | 62 | RawVisibility::Module(path) |
64 | } | 63 | } |
65 | ast::VisibilityKind::PubSuper => { | 64 | ast::VisibilityKind::PubSuper => { |
66 | let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() }; | 65 | let path = ModPath::from_kind(PathKind::Super(1)); |
67 | RawVisibility::Module(path) | 66 | RawVisibility::Module(path) |
68 | } | 67 | } |
69 | ast::VisibilityKind::PubSelf => { | 68 | ast::VisibilityKind::PubSelf => { |
70 | let path = ModPath { kind: PathKind::Plain, segments: Vec::new() }; | 69 | let path = ModPath::from_kind(PathKind::Plain); |
71 | RawVisibility::Module(path) | 70 | RawVisibility::Module(path) |
72 | } | 71 | } |
73 | ast::VisibilityKind::Pub => RawVisibility::Public, | 72 | ast::VisibilityKind::Pub => RawVisibility::Public, |
@@ -103,8 +102,8 @@ impl Visibility { | |||
103 | if from_module.krate != to_module.krate { | 102 | if from_module.krate != to_module.krate { |
104 | return false; | 103 | return false; |
105 | } | 104 | } |
106 | let def_map = db.crate_def_map(from_module.krate); | 105 | let def_map = from_module.def_map(db); |
107 | 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) |
108 | } | 107 | } |
109 | 108 | ||
110 | pub(crate) fn is_visible_from_other_crate(self) -> bool { | 109 | pub(crate) fn is_visible_from_other_crate(self) -> bool { |
@@ -116,26 +115,48 @@ impl Visibility { | |||
116 | 115 | ||
117 | pub(crate) fn is_visible_from_def_map( | 116 | pub(crate) fn is_visible_from_def_map( |
118 | self, | 117 | self, |
119 | def_map: &CrateDefMap, | 118 | db: &dyn DefDatabase, |
120 | from_module: crate::LocalModuleId, | 119 | def_map: &DefMap, |
120 | mut from_module: crate::LocalModuleId, | ||
121 | ) -> bool { | 121 | ) -> bool { |
122 | let to_module = match self { | 122 | let to_module = match self { |
123 | Visibility::Module(m) => m, | 123 | Visibility::Module(m) => m, |
124 | Visibility::Public => return true, | 124 | Visibility::Public => return true, |
125 | }; | 125 | }; |
126 | |||
126 | // from_module needs to be a descendant of to_module | 127 | // from_module needs to be a descendant of to_module |
127 | let mut ancestors = std::iter::successors(Some(from_module), |m| { | 128 | let mut def_map = def_map; |
128 | let parent_id = def_map[*m].parent?; | 129 | let mut parent_arc; |
129 | Some(parent_id) | 130 | loop { |
130 | }); | 131 | if def_map.module_id(from_module) == to_module { |
131 | 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 | } | ||
132 | } | 153 | } |
133 | 154 | ||
134 | /// Returns the most permissive visibility of `self` and `other`. | 155 | /// Returns the most permissive visibility of `self` and `other`. |
135 | /// | 156 | /// |
136 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only | 157 | /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only |
137 | /// visible in unrelated modules). | 158 | /// visible in unrelated modules). |
138 | pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> { | 159 | pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> { |
139 | match (self, other) { | 160 | match (self, other) { |
140 | (Visibility::Module(_), Visibility::Public) | 161 | (Visibility::Module(_), Visibility::Public) |
141 | | (Visibility::Public, Visibility::Module(_)) | 162 | | (Visibility::Public, Visibility::Module(_)) |