diff options
Diffstat (limited to 'crates/ra_hir_def/src/nameres/path_resolution.rs')
-rw-r--r-- | crates/ra_hir_def/src/nameres/path_resolution.rs | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index fd6422d60..c058e70aa 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs | |||
@@ -18,6 +18,7 @@ use test_utils::tested_by; | |||
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::DefDatabase, | 20 | db::DefDatabase, |
21 | item_scope::BUILTIN_SCOPE, | ||
21 | nameres::{BuiltinShadowMode, CrateDefMap}, | 22 | nameres::{BuiltinShadowMode, CrateDefMap}, |
22 | path::{ModPath, PathKind}, | 23 | path::{ModPath, PathKind}, |
23 | per_ns::PerNs, | 24 | per_ns::PerNs, |
@@ -103,15 +104,6 @@ impl CrateDefMap { | |||
103 | path: &ModPath, | 104 | path: &ModPath, |
104 | shadow: BuiltinShadowMode, | 105 | shadow: BuiltinShadowMode, |
105 | ) -> ResolvePathResult { | 106 | ) -> ResolvePathResult { |
106 | // if it is not the last segment, we prefer the module to the builtin | ||
107 | let prefer_module = |index| { | ||
108 | if index == path.segments.len() - 1 { | ||
109 | shadow | ||
110 | } else { | ||
111 | BuiltinShadowMode::Module | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | let mut segments = path.segments.iter().enumerate(); | 107 | let mut segments = path.segments.iter().enumerate(); |
116 | let mut curr_per_ns: PerNs = match path.kind { | 108 | let mut curr_per_ns: PerNs = match path.kind { |
117 | PathKind::DollarCrate(krate) => { | 109 | PathKind::DollarCrate(krate) => { |
@@ -140,20 +132,29 @@ impl CrateDefMap { | |||
140 | if self.edition == Edition::Edition2015 | 132 | if self.edition == Edition::Edition2015 |
141 | && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => | 133 | && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => |
142 | { | 134 | { |
143 | let (idx, segment) = match segments.next() { | 135 | let (_, segment) = match segments.next() { |
144 | Some((idx, segment)) => (idx, segment), | 136 | Some((idx, segment)) => (idx, segment), |
145 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | 137 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), |
146 | }; | 138 | }; |
147 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); | 139 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); |
148 | self.resolve_name_in_crate_root_or_extern_prelude(&segment, prefer_module(idx)) | 140 | self.resolve_name_in_crate_root_or_extern_prelude(&segment) |
149 | } | 141 | } |
150 | PathKind::Plain => { | 142 | PathKind::Plain => { |
151 | let (idx, segment) = match segments.next() { | 143 | let (_, segment) = match segments.next() { |
152 | Some((idx, segment)) => (idx, segment), | 144 | Some((idx, segment)) => (idx, segment), |
153 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | 145 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), |
154 | }; | 146 | }; |
147 | // The first segment may be a builtin type. If the path has more | ||
148 | // than one segment, we first try resolving it as a module | ||
149 | // anyway. | ||
150 | // FIXME: If the next segment doesn't resolve in the module and | ||
151 | // BuiltinShadowMode wasn't Module, then we need to try | ||
152 | // resolving it as a builtin. | ||
153 | let prefer_module = | ||
154 | if path.segments.len() == 1 { shadow } else { BuiltinShadowMode::Module }; | ||
155 | |||
155 | log::debug!("resolving {:?} in module", segment); | 156 | log::debug!("resolving {:?} in module", segment); |
156 | self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx)) | 157 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) |
157 | } | 158 | } |
158 | PathKind::Super(lvl) => { | 159 | PathKind::Super(lvl) => { |
159 | let m = successors(Some(original_module), |m| self.modules[*m].parent) | 160 | let m = successors(Some(original_module), |m| self.modules[*m].parent) |
@@ -216,7 +217,7 @@ impl CrateDefMap { | |||
216 | } | 217 | } |
217 | 218 | ||
218 | // Since it is a qualified path here, it should not contains legacy macros | 219 | // Since it is a qualified path here, it should not contains legacy macros |
219 | self[module.local_id].scope.get(&segment, prefer_module(i)) | 220 | self[module.local_id].scope.get(&segment) |
220 | } | 221 | } |
221 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | 222 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { |
222 | // enum variant | 223 | // enum variant |
@@ -275,33 +276,35 @@ impl CrateDefMap { | |||
275 | .scope | 276 | .scope |
276 | .get_legacy_macro(name) | 277 | .get_legacy_macro(name) |
277 | .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); | 278 | .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); |
278 | let from_scope = self[module].scope.get(name, shadow); | 279 | let from_scope = self[module].scope.get(name); |
280 | let from_builtin = BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none); | ||
281 | let from_scope_or_builtin = match shadow { | ||
282 | BuiltinShadowMode::Module => from_scope.or(from_builtin), | ||
283 | BuiltinShadowMode::Other => { | ||
284 | if let Some(ModuleDefId::ModuleId(_)) = from_scope.take_types() { | ||
285 | from_builtin.or(from_scope) | ||
286 | } else { | ||
287 | from_scope.or(from_builtin) | ||
288 | } | ||
289 | } | ||
290 | }; | ||
279 | let from_extern_prelude = self | 291 | let from_extern_prelude = self |
280 | .extern_prelude | 292 | .extern_prelude |
281 | .get(name) | 293 | .get(name) |
282 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); | 294 | .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); |
283 | let from_prelude = self.resolve_in_prelude(db, name, shadow); | 295 | let from_prelude = self.resolve_in_prelude(db, name); |
284 | 296 | ||
285 | from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) | 297 | from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) |
286 | } | 298 | } |
287 | 299 | ||
288 | fn resolve_name_in_crate_root_or_extern_prelude( | 300 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { |
289 | &self, | 301 | let from_crate_root = self[self.root].scope.get(name); |
290 | name: &Name, | ||
291 | shadow: BuiltinShadowMode, | ||
292 | ) -> PerNs { | ||
293 | let from_crate_root = self[self.root].scope.get(name, shadow); | ||
294 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); | 302 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); |
295 | 303 | ||
296 | from_crate_root.or(from_extern_prelude) | 304 | from_crate_root.or(from_extern_prelude) |
297 | } | 305 | } |
298 | 306 | ||
299 | fn resolve_in_prelude( | 307 | fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs { |
300 | &self, | ||
301 | db: &impl DefDatabase, | ||
302 | name: &Name, | ||
303 | shadow: BuiltinShadowMode, | ||
304 | ) -> PerNs { | ||
305 | if let Some(prelude) = self.prelude { | 308 | if let Some(prelude) = self.prelude { |
306 | let keep; | 309 | let keep; |
307 | let def_map = if prelude.krate == self.krate { | 310 | let def_map = if prelude.krate == self.krate { |
@@ -311,7 +314,7 @@ impl CrateDefMap { | |||
311 | keep = db.crate_def_map(prelude.krate); | 314 | keep = db.crate_def_map(prelude.krate); |
312 | &keep | 315 | &keep |
313 | }; | 316 | }; |
314 | def_map[prelude.local_id].scope.get(name, shadow) | 317 | def_map[prelude.local_id].scope.get(name) |
315 | } else { | 318 | } else { |
316 | PerNs::none() | 319 | PerNs::none() |
317 | } | 320 | } |