diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-09 22:09:23 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-09 22:09:23 +0100 |
commit | c3d96f64ef1b2a5ded9cf5950f8e0f5798de4e1b (patch) | |
tree | a0d6c8121ca6845a48acbb3e9a895a07bfc584ce /crates/ra_hir/src/nameres.rs | |
parent | 5fbdf57c4fe7ee99ba94549766a2644431f61b26 (diff) | |
parent | 5f48ef39024f62c135197e764741354611e02b6f (diff) |
Merge #1795
1795: Make macro scope a real name scope and fix some details r=matklad a=uHOOCCOOHu
This PR make macro's module scope a real name scope in `PerNs`, instead of handling `Either<PerNs, MacroDef>` everywhere.
In `rustc`, the macro scope behave exactly the same as type and value scope.
It is valid that macros, types and values having exact the same name, and a `use` statement will import all of them. This happened to module `alloc::vec` and macro `alloc::vec!`.
So `Either` is not suitable here.
There is a trap that not only does `#[macro_use]` import all `#[macro_export] macro_rules`, but also imports all macros `use`d in the crate root.
In other words, it just _imports all macros in the module scope of crate root_. (Visibility of `use` doesn't matter.)
And it also happened to `libstd` which has `use alloc_crate::vec;` in crate root to re-export `alloc::vec`, which it both a module and a macro.
The current implementation of `#[macro_use] extern crate` doesn't work here, so that is why only macros directly from `libstd` like `dbg!` work, while `vec!` from `liballoc` doesn't.
This PR fixes this.
Another point is that, after some tests, I figure out that _`macro_rules` does NOT define macro in current module scope at all_.
It defines itself in legacy textual scope. And if `#[macro_export]` is given, it also is defined ONLY in module scope of crate root. (Then being `macro_use`d, as mentioned above)
(Well, the nightly [Declarative Macro 2.0](https://github.com/rust-lang/rust/issues/39412) simply always define in current module scope only, just like normal items do. But it is not yet supported by us)
After this PR, in my test, all non-builtin macros are resolved now. (Hover text for documentation is available) So it fixes #1688 . Since compiler builtin macros are marked as `#[rustc_doc_only_macro]` instead of `#[macro_export]`, we can simply tweak the condition to let it resolved, but it may cause expansion error.
Some critical notes are also given in doc-comments.
<img width="447" alt="Screenshot_20190909_223859" src="https://user-images.githubusercontent.com/14816024/64540366-ac1ef600-d352-11e9-804f-566ba7559206.png">
Co-authored-by: uHOOCCOOHu <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/nameres.rs')
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 158 |
1 files changed, 65 insertions, 93 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 74546e5e2..7488d75a5 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -67,7 +67,6 @@ use test_utils::tested_by; | |||
67 | use crate::{ | 67 | use crate::{ |
68 | db::{AstDatabase, DefDatabase}, | 68 | db::{AstDatabase, DefDatabase}, |
69 | diagnostics::DiagnosticSink, | 69 | diagnostics::DiagnosticSink, |
70 | either::Either, | ||
71 | ids::MacroDefId, | 70 | ids::MacroDefId, |
72 | nameres::diagnostics::DefDiagnostic, | 71 | nameres::diagnostics::DefDiagnostic, |
73 | AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait, | 72 | AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait, |
@@ -105,8 +104,6 @@ pub struct CrateDefMap { | |||
105 | /// However, do we want to put it as a global variable? | 104 | /// However, do we want to put it as a global variable? |
106 | poison_macros: FxHashSet<MacroDefId>, | 105 | poison_macros: FxHashSet<MacroDefId>, |
107 | 106 | ||
108 | exported_macros: FxHashMap<Name, MacroDefId>, | ||
109 | |||
110 | diagnostics: Vec<DefDiagnostic>, | 107 | diagnostics: Vec<DefDiagnostic>, |
111 | } | 108 | } |
112 | 109 | ||
@@ -138,12 +135,6 @@ pub(crate) struct ModuleData { | |||
138 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 135 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
139 | pub struct ModuleScope { | 136 | pub struct ModuleScope { |
140 | items: FxHashMap<Name, Resolution>, | 137 | items: FxHashMap<Name, Resolution>, |
141 | /// Macros in current module scoped | ||
142 | /// | ||
143 | /// This scope works exactly the same way that item scoping does. | ||
144 | /// Macro invocation with quantified path will search in it. | ||
145 | /// See details below. | ||
146 | macros: FxHashMap<Name, MacroDef>, | ||
147 | /// Macros visable in current module in legacy textual scope | 138 | /// Macros visable in current module in legacy textual scope |
148 | /// | 139 | /// |
149 | /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. | 140 | /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. |
@@ -152,6 +143,10 @@ pub struct ModuleScope { | |||
152 | /// and only normal scoped `macros` will be searched in. | 143 | /// and only normal scoped `macros` will be searched in. |
153 | /// | 144 | /// |
154 | /// Note that this automatically inherit macros defined textually before the definition of module itself. | 145 | /// Note that this automatically inherit macros defined textually before the definition of module itself. |
146 | /// | ||
147 | /// Module scoped macros will be inserted into `items` instead of here. | ||
148 | // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will | ||
149 | // be all resolved to the last one defined if shadowing happens. | ||
155 | legacy_macros: FxHashMap<Name, MacroDef>, | 150 | legacy_macros: FxHashMap<Name, MacroDef>, |
156 | } | 151 | } |
157 | 152 | ||
@@ -164,35 +159,43 @@ static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| { | |||
164 | .collect() | 159 | .collect() |
165 | }); | 160 | }); |
166 | 161 | ||
162 | /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. | ||
163 | /// Other methods will only resolve values, types and module scoped macros only. | ||
167 | impl ModuleScope { | 164 | impl ModuleScope { |
168 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a { | 165 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a { |
169 | //FIXME: shadowing | 166 | //FIXME: shadowing |
170 | self.items.iter().chain(BUILTIN_SCOPE.iter()) | 167 | self.items.iter().chain(BUILTIN_SCOPE.iter()) |
171 | } | 168 | } |
169 | |||
170 | /// Iterate over all module scoped macros | ||
171 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a { | ||
172 | self.items | ||
173 | .iter() | ||
174 | .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_))) | ||
175 | } | ||
176 | |||
177 | /// Iterate over all legacy textual scoped macros visable at the end of the module | ||
178 | pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a { | ||
179 | self.legacy_macros.iter().map(|(name, def)| (name, *def)) | ||
180 | } | ||
181 | |||
182 | /// Get a name from current module scope, legacy macros are not included | ||
172 | pub fn get(&self, name: &Name) -> Option<&Resolution> { | 183 | pub fn get(&self, name: &Name) -> Option<&Resolution> { |
173 | self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)) | 184 | self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)) |
174 | } | 185 | } |
186 | |||
175 | pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a { | 187 | pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a { |
176 | self.items.values().filter_map(|r| match r.def.take_types() { | 188 | self.items.values().filter_map(|r| match r.def.take_types() { |
177 | Some(ModuleDef::Trait(t)) => Some(t), | 189 | Some(ModuleDef::Trait(t)) => Some(t), |
178 | _ => None, | 190 | _ => None, |
179 | }) | 191 | }) |
180 | } | 192 | } |
181 | /// It resolves in module scope. Textual scoped macros are ignored here. | 193 | |
182 | fn get_item_or_macro(&self, name: &Name) -> Option<ItemOrMacro> { | ||
183 | match (self.get(name), self.macros.get(name)) { | ||
184 | (Some(item), _) if !item.def.is_none() => Some(Either::A(item.def)), | ||
185 | (_, Some(macro_)) => Some(Either::B(*macro_)), | ||
186 | _ => None, | ||
187 | } | ||
188 | } | ||
189 | fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> { | 194 | fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> { |
190 | self.legacy_macros.get(name).copied() | 195 | self.legacy_macros.get(name).copied() |
191 | } | 196 | } |
192 | } | 197 | } |
193 | 198 | ||
194 | type ItemOrMacro = Either<PerNs<ModuleDef>, MacroDef>; | ||
195 | |||
196 | #[derive(Debug, Clone, PartialEq, Eq, Default)] | 199 | #[derive(Debug, Clone, PartialEq, Eq, Default)] |
197 | pub struct Resolution { | 200 | pub struct Resolution { |
198 | /// None for unresolved | 201 | /// None for unresolved |
@@ -201,20 +204,26 @@ pub struct Resolution { | |||
201 | pub import: Option<ImportId>, | 204 | pub import: Option<ImportId>, |
202 | } | 205 | } |
203 | 206 | ||
207 | impl Resolution { | ||
208 | pub(crate) fn from_macro(macro_: MacroDef) -> Self { | ||
209 | Resolution { def: PerNs::macros(macro_), import: None } | ||
210 | } | ||
211 | } | ||
212 | |||
204 | #[derive(Debug, Clone)] | 213 | #[derive(Debug, Clone)] |
205 | struct ResolvePathResult { | 214 | struct ResolvePathResult { |
206 | resolved_def: ItemOrMacro, | 215 | resolved_def: PerNs<ModuleDef>, |
207 | segment_index: Option<usize>, | 216 | segment_index: Option<usize>, |
208 | reached_fixedpoint: ReachedFixedPoint, | 217 | reached_fixedpoint: ReachedFixedPoint, |
209 | } | 218 | } |
210 | 219 | ||
211 | impl ResolvePathResult { | 220 | impl ResolvePathResult { |
212 | fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { | 221 | fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { |
213 | ResolvePathResult::with(Either::A(PerNs::none()), reached_fixedpoint, None) | 222 | ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None) |
214 | } | 223 | } |
215 | 224 | ||
216 | fn with( | 225 | fn with( |
217 | resolved_def: ItemOrMacro, | 226 | resolved_def: PerNs<ModuleDef>, |
218 | reached_fixedpoint: ReachedFixedPoint, | 227 | reached_fixedpoint: ReachedFixedPoint, |
219 | segment_index: Option<usize>, | 228 | segment_index: Option<usize>, |
220 | ) -> ResolvePathResult { | 229 | ) -> ResolvePathResult { |
@@ -234,21 +243,6 @@ enum ReachedFixedPoint { | |||
234 | No, | 243 | No, |
235 | } | 244 | } |
236 | 245 | ||
237 | /// helper function for select item or macro to use | ||
238 | fn or(left: ItemOrMacro, right: ItemOrMacro) -> ItemOrMacro { | ||
239 | match (left, right) { | ||
240 | (Either::A(s), Either::A(o)) => Either::A(s.or(o)), | ||
241 | (Either::B(s), _) => Either::B(s), | ||
242 | (Either::A(s), Either::B(o)) => { | ||
243 | if !s.is_none() { | ||
244 | Either::A(s) | ||
245 | } else { | ||
246 | Either::B(o) | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | |||
252 | impl CrateDefMap { | 246 | impl CrateDefMap { |
253 | pub(crate) fn crate_def_map_query( | 247 | pub(crate) fn crate_def_map_query( |
254 | // Note that this doesn't have `+ AstDatabase`! | 248 | // Note that this doesn't have `+ AstDatabase`! |
@@ -269,7 +263,6 @@ impl CrateDefMap { | |||
269 | root, | 263 | root, |
270 | modules, | 264 | modules, |
271 | poison_macros: FxHashSet::default(), | 265 | poison_macros: FxHashSet::default(), |
272 | exported_macros: FxHashMap::default(), | ||
273 | diagnostics: Vec::new(), | 266 | diagnostics: Vec::new(), |
274 | } | 267 | } |
275 | }; | 268 | }; |
@@ -328,16 +321,6 @@ impl CrateDefMap { | |||
328 | path: &Path, | 321 | path: &Path, |
329 | ) -> (PerNs<ModuleDef>, Option<usize>) { | 322 | ) -> (PerNs<ModuleDef>, Option<usize>) { |
330 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); | 323 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); |
331 | (res.resolved_def.a().unwrap_or_else(PerNs::none), res.segment_index) | ||
332 | } | ||
333 | |||
334 | pub(crate) fn resolve_path_with_macro( | ||
335 | &self, | ||
336 | db: &impl DefDatabase, | ||
337 | original_module: CrateModuleId, | ||
338 | path: &Path, | ||
339 | ) -> (ItemOrMacro, Option<usize>) { | ||
340 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); | ||
341 | (res.resolved_def, res.segment_index) | 324 | (res.resolved_def, res.segment_index) |
342 | } | 325 | } |
343 | 326 | ||
@@ -351,13 +334,13 @@ impl CrateDefMap { | |||
351 | path: &Path, | 334 | path: &Path, |
352 | ) -> ResolvePathResult { | 335 | ) -> ResolvePathResult { |
353 | let mut segments = path.segments.iter().enumerate(); | 336 | let mut segments = path.segments.iter().enumerate(); |
354 | let mut curr_per_ns: ItemOrMacro = match path.kind { | 337 | let mut curr_per_ns: PerNs<ModuleDef> = match path.kind { |
355 | PathKind::Crate => { | 338 | PathKind::Crate => { |
356 | Either::A(PerNs::types(Module { krate: self.krate, module_id: self.root }.into())) | 339 | PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) |
340 | } | ||
341 | PathKind::Self_ => { | ||
342 | PerNs::types(Module { krate: self.krate, module_id: original_module }.into()) | ||
357 | } | 343 | } |
358 | PathKind::Self_ => Either::A(PerNs::types( | ||
359 | Module { krate: self.krate, module_id: original_module }.into(), | ||
360 | )), | ||
361 | // plain import or absolute path in 2015: crate-relative with | 344 | // plain import or absolute path in 2015: crate-relative with |
362 | // fallback to extern prelude (with the simplification in | 345 | // fallback to extern prelude (with the simplification in |
363 | // rust-lang/rust#57745) | 346 | // rust-lang/rust#57745) |
@@ -379,11 +362,11 @@ impl CrateDefMap { | |||
379 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | 362 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), |
380 | }; | 363 | }; |
381 | log::debug!("resolving {:?} in module", segment); | 364 | log::debug!("resolving {:?} in module", segment); |
382 | self.resolve_name_in_module_with_macro(db, original_module, &segment.name) | 365 | self.resolve_name_in_module(db, original_module, &segment.name) |
383 | } | 366 | } |
384 | PathKind::Super => { | 367 | PathKind::Super => { |
385 | if let Some(p) = self.modules[original_module].parent { | 368 | if let Some(p) = self.modules[original_module].parent { |
386 | Either::A(PerNs::types(Module { krate: self.krate, module_id: p }.into())) | 369 | PerNs::types(Module { krate: self.krate, module_id: p }.into()) |
387 | } else { | 370 | } else { |
388 | log::debug!("super path in root module"); | 371 | log::debug!("super path in root module"); |
389 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 372 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); |
@@ -397,7 +380,7 @@ impl CrateDefMap { | |||
397 | }; | 380 | }; |
398 | if let Some(def) = self.extern_prelude.get(&segment.name) { | 381 | if let Some(def) = self.extern_prelude.get(&segment.name) { |
399 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | 382 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); |
400 | Either::A(PerNs::types(*def)) | 383 | PerNs::types(*def) |
401 | } else { | 384 | } else { |
402 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude | 385 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude |
403 | } | 386 | } |
@@ -405,7 +388,7 @@ impl CrateDefMap { | |||
405 | }; | 388 | }; |
406 | 389 | ||
407 | for (i, segment) in segments { | 390 | for (i, segment) in segments { |
408 | let curr = match curr_per_ns.as_ref().a().and_then(|m| m.as_ref().take_types()) { | 391 | let curr = match curr_per_ns.as_ref().take_types() { |
409 | Some(r) => r, | 392 | Some(r) => r, |
410 | None => { | 393 | None => { |
411 | // we still have path segments left, but the path so far | 394 | // we still have path segments left, but the path so far |
@@ -425,8 +408,7 @@ impl CrateDefMap { | |||
425 | Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; | 408 | Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; |
426 | log::debug!("resolving {:?} in other crate", path); | 409 | log::debug!("resolving {:?} in other crate", path); |
427 | let defp_map = db.crate_def_map(module.krate); | 410 | let defp_map = db.crate_def_map(module.krate); |
428 | let (def, s) = | 411 | let (def, s) = defp_map.resolve_path(db, module.module_id, &path); |
429 | defp_map.resolve_path_with_macro(db, module.module_id, &path); | ||
430 | return ResolvePathResult::with( | 412 | return ResolvePathResult::with( |
431 | def, | 413 | def, |
432 | ReachedFixedPoint::Yes, | 414 | ReachedFixedPoint::Yes, |
@@ -434,8 +416,9 @@ impl CrateDefMap { | |||
434 | ); | 416 | ); |
435 | } | 417 | } |
436 | 418 | ||
437 | match self[module.module_id].scope.get_item_or_macro(&segment.name) { | 419 | // Since it is a quantified path here, it should not contains legacy macros |
438 | Some(res) => res, | 420 | match self[module.module_id].scope.get(&segment.name) { |
421 | Some(res) => res.def, | ||
439 | _ => { | 422 | _ => { |
440 | log::debug!("path segment {:?} not found", segment.name); | 423 | log::debug!("path segment {:?} not found", segment.name); |
441 | return ResolvePathResult::empty(ReachedFixedPoint::No); | 424 | return ResolvePathResult::empty(ReachedFixedPoint::No); |
@@ -446,10 +429,10 @@ impl CrateDefMap { | |||
446 | // enum variant | 429 | // enum variant |
447 | tested_by!(can_import_enum_variant); | 430 | tested_by!(can_import_enum_variant); |
448 | match e.variant(db, &segment.name) { | 431 | match e.variant(db, &segment.name) { |
449 | Some(variant) => Either::A(PerNs::both(variant.into(), variant.into())), | 432 | Some(variant) => PerNs::both(variant.into(), variant.into()), |
450 | None => { | 433 | None => { |
451 | return ResolvePathResult::with( | 434 | return ResolvePathResult::with( |
452 | Either::A(PerNs::types((*e).into())), | 435 | PerNs::types((*e).into()), |
453 | ReachedFixedPoint::Yes, | 436 | ReachedFixedPoint::Yes, |
454 | Some(i), | 437 | Some(i), |
455 | ); | 438 | ); |
@@ -466,7 +449,7 @@ impl CrateDefMap { | |||
466 | ); | 449 | ); |
467 | 450 | ||
468 | return ResolvePathResult::with( | 451 | return ResolvePathResult::with( |
469 | Either::A(PerNs::types(*s)), | 452 | PerNs::types(*s), |
470 | ReachedFixedPoint::Yes, | 453 | ReachedFixedPoint::Yes, |
471 | Some(i), | 454 | Some(i), |
472 | ); | 455 | ); |
@@ -476,14 +459,12 @@ impl CrateDefMap { | |||
476 | ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) | 459 | ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) |
477 | } | 460 | } |
478 | 461 | ||
479 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> ItemOrMacro { | 462 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { |
480 | let from_crate_root = self[self.root] | 463 | let from_crate_root = |
481 | .scope | 464 | self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def); |
482 | .get_item_or_macro(name) | ||
483 | .unwrap_or_else(|| Either::A(PerNs::none())); | ||
484 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); | 465 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); |
485 | 466 | ||
486 | or(from_crate_root, Either::A(from_extern_prelude)) | 467 | from_crate_root.or(from_extern_prelude) |
487 | } | 468 | } |
488 | 469 | ||
489 | pub(crate) fn resolve_name_in_module( | 470 | pub(crate) fn resolve_name_in_module( |
@@ -492,47 +473,38 @@ impl CrateDefMap { | |||
492 | module: CrateModuleId, | 473 | module: CrateModuleId, |
493 | name: &Name, | 474 | name: &Name, |
494 | ) -> PerNs<ModuleDef> { | 475 | ) -> PerNs<ModuleDef> { |
495 | self.resolve_name_in_module_with_macro(db, module, name).a().unwrap_or_else(PerNs::none) | ||
496 | } | ||
497 | |||
498 | fn resolve_name_in_module_with_macro( | ||
499 | &self, | ||
500 | db: &impl DefDatabase, | ||
501 | module: CrateModuleId, | ||
502 | name: &Name, | ||
503 | ) -> ItemOrMacro { | ||
504 | // Resolve in: | 476 | // Resolve in: |
505 | // - legacy scope | 477 | // - legacy scope of macro |
506 | // - current module / scope | 478 | // - current module / scope |
507 | // - extern prelude | 479 | // - extern prelude |
508 | // - std prelude | 480 | // - std prelude |
509 | let from_legacy_macro = self[module] | 481 | let from_legacy_macro = |
510 | .scope | 482 | self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); |
511 | .get_legacy_macro(name) | 483 | let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def); |
512 | .map_or_else(|| Either::A(PerNs::none()), Either::B); | ||
513 | let from_scope = | ||
514 | self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none())); | ||
515 | let from_extern_prelude = | 484 | let from_extern_prelude = |
516 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 485 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); |
517 | let from_prelude = self.resolve_in_prelude(db, name); | 486 | let from_prelude = self.resolve_in_prelude(db, name); |
518 | 487 | ||
519 | or(from_legacy_macro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) | 488 | from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) |
520 | } | 489 | } |
521 | 490 | ||
522 | fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { | 491 | fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { |
523 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) | 492 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) |
524 | } | 493 | } |
525 | 494 | ||
526 | fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> ItemOrMacro { | 495 | fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs<ModuleDef> { |
527 | if let Some(prelude) = self.prelude { | 496 | if let Some(prelude) = self.prelude { |
528 | let resolution = if prelude.krate == self.krate { | 497 | let keep; |
529 | self[prelude.module_id].scope.get_item_or_macro(name) | 498 | let def_map = if prelude.krate == self.krate { |
499 | self | ||
530 | } else { | 500 | } else { |
531 | db.crate_def_map(prelude.krate)[prelude.module_id].scope.get_item_or_macro(name) | 501 | // Extend lifetime |
502 | keep = db.crate_def_map(prelude.krate); | ||
503 | &keep | ||
532 | }; | 504 | }; |
533 | resolution.unwrap_or_else(|| Either::A(PerNs::none())) | 505 | def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def) |
534 | } else { | 506 | } else { |
535 | Either::A(PerNs::none()) | 507 | PerNs::none() |
536 | } | 508 | } |
537 | } | 509 | } |
538 | } | 510 | } |