aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres/path_resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres/path_resolution.rs')
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs55
1 files changed, 40 insertions, 15 deletions
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index b72c55bd1..42a75226b 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -16,7 +16,7 @@ use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 db::DefDatabase, 18 db::DefDatabase,
19 nameres::CrateDefMap, 19 nameres::{BuiltinShadowMode, CrateDefMap},
20 path::{Path, PathKind}, 20 path::{Path, PathKind},
21 per_ns::PerNs, 21 per_ns::PerNs,
22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, 22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
@@ -68,7 +68,17 @@ impl CrateDefMap {
68 mode: ResolveMode, 68 mode: ResolveMode,
69 original_module: LocalModuleId, 69 original_module: LocalModuleId,
70 path: &Path, 70 path: &Path,
71 shadow: BuiltinShadowMode,
71 ) -> ResolvePathResult { 72 ) -> ResolvePathResult {
73 // if it is not the last segment, we prefer the module to the builtin
74 let prefer_module = |index| {
75 if index == path.segments.len() - 1 {
76 shadow
77 } else {
78 BuiltinShadowMode::Module
79 }
80 };
81
72 let mut segments = path.segments.iter().enumerate(); 82 let mut segments = path.segments.iter().enumerate();
73 let mut curr_per_ns: PerNs = match path.kind { 83 let mut curr_per_ns: PerNs = match path.kind {
74 PathKind::DollarCrate(krate) => { 84 PathKind::DollarCrate(krate) => {
@@ -96,20 +106,20 @@ impl CrateDefMap {
96 if self.edition == Edition::Edition2015 106 if self.edition == Edition::Edition2015
97 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => 107 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
98 { 108 {
99 let segment = match segments.next() { 109 let (idx, segment) = match segments.next() {
100 Some((_, segment)) => segment, 110 Some((idx, segment)) => (idx, segment),
101 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 111 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
102 }; 112 };
103 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 113 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
104 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name) 114 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name, prefer_module(idx))
105 } 115 }
106 PathKind::Plain => { 116 PathKind::Plain => {
107 let segment = match segments.next() { 117 let (idx, segment) = match segments.next() {
108 Some((_, segment)) => segment, 118 Some((idx, segment)) => (idx, segment),
109 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 119 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
110 }; 120 };
111 log::debug!("resolving {:?} in module", segment); 121 log::debug!("resolving {:?} in module", segment);
112 self.resolve_name_in_module(db, original_module, &segment.name) 122 self.resolve_name_in_module(db, original_module, &segment.name, prefer_module(idx))
113 } 123 }
114 PathKind::Super => { 124 PathKind::Super => {
115 if let Some(p) = self.modules[original_module].parent { 125 if let Some(p) = self.modules[original_module].parent {
@@ -160,7 +170,7 @@ impl CrateDefMap {
160 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; 170 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
161 log::debug!("resolving {:?} in other crate", path); 171 log::debug!("resolving {:?} in other crate", path);
162 let defp_map = db.crate_def_map(module.krate); 172 let defp_map = db.crate_def_map(module.krate);
163 let (def, s) = defp_map.resolve_path(db, module.local_id, &path); 173 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
164 return ResolvePathResult::with( 174 return ResolvePathResult::with(
165 def, 175 def,
166 ReachedFixedPoint::Yes, 176 ReachedFixedPoint::Yes,
@@ -169,7 +179,7 @@ impl CrateDefMap {
169 } 179 }
170 180
171 // Since it is a qualified path here, it should not contains legacy macros 181 // Since it is a qualified path here, it should not contains legacy macros
172 match self[module.local_id].scope.get(&segment.name) { 182 match self[module.local_id].scope.get(&segment.name, prefer_module(i)) {
173 Some(res) => res.def, 183 Some(res) => res.def,
174 _ => { 184 _ => {
175 log::debug!("path segment {:?} not found", segment.name); 185 log::debug!("path segment {:?} not found", segment.name);
@@ -212,6 +222,7 @@ impl CrateDefMap {
212 } 222 }
213 }; 223 };
214 } 224 }
225
215 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) 226 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
216 } 227 }
217 228
@@ -220,6 +231,7 @@ impl CrateDefMap {
220 db: &impl DefDatabase, 231 db: &impl DefDatabase,
221 module: LocalModuleId, 232 module: LocalModuleId,
222 name: &Name, 233 name: &Name,
234 shadow: BuiltinShadowMode,
223 ) -> PerNs { 235 ) -> PerNs {
224 // Resolve in: 236 // Resolve in:
225 // - legacy scope of macro 237 // - legacy scope of macro
@@ -228,23 +240,33 @@ impl CrateDefMap {
228 // - std prelude 240 // - std prelude
229 let from_legacy_macro = 241 let from_legacy_macro =
230 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); 242 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
231 let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def); 243 let from_scope =
244 self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
232 let from_extern_prelude = 245 let from_extern_prelude =
233 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 246 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
234 let from_prelude = self.resolve_in_prelude(db, name); 247 let from_prelude = self.resolve_in_prelude(db, name, shadow);
235 248
236 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) 249 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
237 } 250 }
238 251
239 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { 252 fn resolve_name_in_crate_root_or_extern_prelude(
253 &self,
254 name: &Name,
255 shadow: BuiltinShadowMode,
256 ) -> PerNs {
240 let from_crate_root = 257 let from_crate_root =
241 self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def); 258 self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
242 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 259 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
243 260
244 from_crate_root.or(from_extern_prelude) 261 from_crate_root.or(from_extern_prelude)
245 } 262 }
246 263
247 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs { 264 fn resolve_in_prelude(
265 &self,
266 db: &impl DefDatabase,
267 name: &Name,
268 shadow: BuiltinShadowMode,
269 ) -> PerNs {
248 if let Some(prelude) = self.prelude { 270 if let Some(prelude) = self.prelude {
249 let keep; 271 let keep;
250 let def_map = if prelude.krate == self.krate { 272 let def_map = if prelude.krate == self.krate {
@@ -254,7 +276,10 @@ impl CrateDefMap {
254 keep = db.crate_def_map(prelude.krate); 276 keep = db.crate_def_map(prelude.krate);
255 &keep 277 &keep
256 }; 278 };
257 def_map[prelude.local_id].scope.get(name).map_or_else(PerNs::none, |res| res.def) 279 def_map[prelude.local_id]
280 .scope
281 .get(name, shadow)
282 .map_or_else(PerNs::none, |res| res.def)
258 } else { 283 } else {
259 PerNs::none() 284 PerNs::none()
260 } 285 }