aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-10 19:44:34 +0000
committerFlorian Diebold <[email protected]>2019-02-13 19:10:09 +0000
commit1526eb25c98fd16a9c0d114d0ed44e8fec1cc19c (patch)
tree1acf0f556de14a2fac88929db9af96025a47f79f /crates/ra_hir/src/nameres.rs
parent65266c644a31e6b321e5afb3c5a2ee75be76cb0c (diff)
Import the prelude
Diffstat (limited to 'crates/ra_hir/src/nameres.rs')
-rw-r--r--crates/ra_hir/src/nameres.rs50
1 files changed, 46 insertions, 4 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index ffb20d564..2ba6038c6 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -34,6 +34,10 @@ use crate::{
34/// module, the set of visible items. 34/// module, the set of visible items.
35#[derive(Default, Debug, PartialEq, Eq)] 35#[derive(Default, Debug, PartialEq, Eq)]
36pub struct ItemMap { 36pub struct ItemMap {
37 /// The prelude module for this crate. This either comes from an import
38 /// marked with the `prelude_import` attribute, or (in the normal case) from
39 /// a dependency (`std` or `core`).
40 prelude: Option<Module>,
37 pub(crate) extern_prelude: FxHashMap<Name, ModuleDef>, 41 pub(crate) extern_prelude: FxHashMap<Name, ModuleDef>,
38 per_module: ArenaMap<ModuleId, ModuleScope>, 42 per_module: ArenaMap<ModuleId, ModuleScope>,
39} 43}
@@ -211,6 +215,13 @@ where
211 if let Some(module) = dep.krate.root_module(self.db) { 215 if let Some(module) = dep.krate.root_module(self.db) {
212 self.result.extern_prelude.insert(dep.name.clone(), module.into()); 216 self.result.extern_prelude.insert(dep.name.clone(), module.into());
213 } 217 }
218 // look for the prelude
219 if self.result.prelude.is_none() {
220 let item_map = self.db.item_map(dep.krate);
221 if item_map.prelude.is_some() {
222 self.result.prelude = item_map.prelude;
223 }
224 }
214 } 225 }
215 } 226 }
216 227
@@ -279,7 +290,10 @@ where
279 log::debug!("glob import: {:?}", import); 290 log::debug!("glob import: {:?}", import);
280 match def.take_types() { 291 match def.take_types() {
281 Some(ModuleDef::Module(m)) => { 292 Some(ModuleDef::Module(m)) => {
282 if m.krate != self.krate { 293 if import.is_prelude {
294 tested_by!(std_prelude);
295 self.result.prelude = Some(m);
296 } else if m.krate != self.krate {
283 tested_by!(glob_across_crates); 297 tested_by!(glob_across_crates);
284 // glob import from other crate => we can just import everything once 298 // glob import from other crate => we can just import everything once
285 let item_map = self.db.item_map(m.krate); 299 let item_map = self.db.item_map(m.krate);
@@ -434,12 +448,40 @@ impl ItemMap {
434 self.resolve_path_fp(db, original_module, path).0 448 self.resolve_path_fp(db, original_module, path).0
435 } 449 }
436 450
437 pub(crate) fn resolve_name_in_module(&self, module: Module, name: &Name) -> PerNs<ModuleDef> { 451 fn resolve_in_prelude(
452 &self,
453 db: &impl PersistentHirDatabase,
454 original_module: Module,
455 name: &Name,
456 ) -> PerNs<ModuleDef> {
457 if let Some(prelude) = self.prelude {
458 let resolution = if prelude.krate == original_module.krate {
459 self[prelude.module_id].items.get(name).cloned()
460 } else {
461 db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned()
462 };
463 resolution.map(|r| r.def).unwrap_or_else(PerNs::none)
464 } else {
465 PerNs::none()
466 }
467 }
468
469 pub(crate) fn resolve_name_in_module(
470 &self,
471 db: &impl PersistentHirDatabase,
472 module: Module,
473 name: &Name,
474 ) -> PerNs<ModuleDef> {
475 // Resolve in:
476 // - current module / scope
477 // - extern prelude
478 // - std prelude
438 let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.def); 479 let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.def);
439 let from_extern_prelude = 480 let from_extern_prelude =
440 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 481 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
482 let from_prelude = self.resolve_in_prelude(db, module, name);
441 483
442 from_scope.or(from_extern_prelude) 484 from_scope.or(from_extern_prelude).or(from_prelude)
443 } 485 }
444 486
445 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 487 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
@@ -459,7 +501,7 @@ impl ItemMap {
459 Some((_, segment)) => segment, 501 Some((_, segment)) => segment,
460 None => return (PerNs::none(), ReachedFixedPoint::Yes), 502 None => return (PerNs::none(), ReachedFixedPoint::Yes),
461 }; 503 };
462 self.resolve_name_in_module(original_module, &segment.name) 504 self.resolve_name_in_module(db, original_module, &segment.name)
463 } 505 }
464 PathKind::Super => { 506 PathKind::Super => {
465 if let Some(p) = original_module.parent(db) { 507 if let Some(p) = original_module.parent(db) {