aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
committerSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
commit15ea338ac991707d330288ba4d1bf5daa0fc75d9 (patch)
tree16aeab28bcdb07d36aae28e3fb4a385614865a48 /crates/ra_hir_def/src/nameres
parenteb7363d167c7a9f7c73cb950b621eb1dce493318 (diff)
parentf7f9757b6b144385ab8ce57b15764473b1f57331 (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs141
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs17
-rw-r--r--crates/ra_hir_def/src/nameres/per_ns.rs74
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs76
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs2
7 files changed, 125 insertions, 195 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index aae3dcadf..41becf8df 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -1,4 +1,7 @@
1//! FIXME: write short doc here 1//! The core of the module-level name resolution algorithm.
2//!
3//! `DefCollector::collect` contains the fixed-point iteration loop which
4//! resolves imports and expands macros.
2 5
3use hir_expand::{ 6use hir_expand::{
4 builtin_macro::find_builtin_macro, 7 builtin_macro::find_builtin_macro,
@@ -7,24 +10,25 @@ use hir_expand::{
7}; 10};
8use ra_cfg::CfgOptions; 11use ra_cfg::CfgOptions;
9use ra_db::{CrateId, FileId}; 12use ra_db::{CrateId, FileId};
10use ra_syntax::{ast, SmolStr}; 13use ra_syntax::ast;
11use rustc_hash::FxHashMap; 14use rustc_hash::{FxHashMap, FxHashSet};
12use test_utils::tested_by; 15use test_utils::tested_by;
13 16
14use crate::{ 17use crate::{
15 attr::Attr, 18 attr::Attrs,
16 db::DefDatabase2, 19 db::DefDatabase,
17 nameres::{ 20 nameres::{
18 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 21 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 22 raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 23 },
21 path::{Path, PathKind}, 24 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId, 25 per_ns::PerNs,
23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, 26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
24 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 28 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
25}; 29};
26 30
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
28 let crate_graph = db.crate_graph(); 32 let crate_graph = db.crate_graph();
29 33
30 // populate external prelude 34 // populate external prelude
@@ -56,6 +60,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) ->
56 unexpanded_macros: Vec::new(), 60 unexpanded_macros: Vec::new(),
57 mod_dirs: FxHashMap::default(), 61 mod_dirs: FxHashMap::default(),
58 macro_stack_monitor: MacroStackMonitor::default(), 62 macro_stack_monitor: MacroStackMonitor::default(),
63 poison_macros: FxHashSet::default(),
59 cfg_options, 64 cfg_options,
60 }; 65 };
61 collector.collect(); 66 collector.collect();
@@ -94,21 +99,32 @@ impl MacroStackMonitor {
94struct DefCollector<'a, DB> { 99struct DefCollector<'a, DB> {
95 db: &'a DB, 100 db: &'a DB,
96 def_map: CrateDefMap, 101 def_map: CrateDefMap,
97 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 102 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
98 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 103 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>,
99 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>, 104 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>,
100 mod_dirs: FxHashMap<CrateModuleId, ModDir>, 105 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
101 106
102 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 107 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
103 /// To prevent stack overflow, we add a deep counter here for prevent that. 108 /// To prevent stack overflow, we add a deep counter here for prevent that.
104 macro_stack_monitor: MacroStackMonitor, 109 macro_stack_monitor: MacroStackMonitor,
110 /// Some macros are not well-behavior, which leads to infinite loop
111 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
112 /// We mark it down and skip it in collector
113 ///
114 /// FIXME:
115 /// Right now it only handle a poison macro in a single crate,
116 /// such that if other crate try to call that macro,
117 /// the whole process will do again until it became poisoned in that crate.
118 /// We should handle this macro set globally
119 /// However, do we want to put it as a global variable?
120 poison_macros: FxHashSet<MacroDefId>,
105 121
106 cfg_options: &'a CfgOptions, 122 cfg_options: &'a CfgOptions,
107} 123}
108 124
109impl<DB> DefCollector<'_, DB> 125impl<DB> DefCollector<'_, DB>
110where 126where
111 DB: DefDatabase2, 127 DB: DefDatabase,
112{ 128{
113 fn collect(&mut self) { 129 fn collect(&mut self) {
114 let crate_graph = self.db.crate_graph(); 130 let crate_graph = self.db.crate_graph();
@@ -173,7 +189,7 @@ where
173 /// ``` 189 /// ```
174 fn define_macro( 190 fn define_macro(
175 &mut self, 191 &mut self,
176 module_id: CrateModuleId, 192 module_id: LocalModuleId,
177 name: Name, 193 name: Name,
178 macro_: MacroDefId, 194 macro_: MacroDefId,
179 export: bool, 195 export: bool,
@@ -200,7 +216,7 @@ where
200 /// the definition of current module. 216 /// the definition of current module.
201 /// And also, `macro_use` on a module will import all legacy macros visable inside to 217 /// And also, `macro_use` on a module will import all legacy macros visable inside to
202 /// current legacy scope, with possible shadowing. 218 /// current legacy scope, with possible shadowing.
203 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDefId) { 219 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
204 // Always shadowing 220 // Always shadowing
205 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); 221 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
206 } 222 }
@@ -208,7 +224,7 @@ where
208 /// Import macros from `#[macro_use] extern crate`. 224 /// Import macros from `#[macro_use] extern crate`.
209 fn import_macros_from_extern_crate( 225 fn import_macros_from_extern_crate(
210 &mut self, 226 &mut self,
211 current_module_id: CrateModuleId, 227 current_module_id: LocalModuleId,
212 import: &raw::ImportData, 228 import: &raw::ImportData,
213 ) { 229 ) {
214 log::debug!( 230 log::debug!(
@@ -235,7 +251,7 @@ where
235 /// Exported macros are just all macros in the root module scope. 251 /// Exported macros are just all macros in the root module scope.
236 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases 252 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
237 /// created by `use` in the root module, ignoring the visibility of `use`. 253 /// created by `use` in the root module, ignoring the visibility of `use`.
238 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: CrateId) { 254 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
239 let def_map = self.db.crate_def_map(krate); 255 let def_map = self.db.crate_def_map(krate);
240 for (name, def) in def_map[def_map.root].scope.macros() { 256 for (name, def) in def_map[def_map.root].scope.macros() {
241 // `macro_use` only bring things into legacy scope. 257 // `macro_use` only bring things into legacy scope.
@@ -265,7 +281,7 @@ where
265 281
266 fn resolve_import( 282 fn resolve_import(
267 &self, 283 &self,
268 module_id: CrateModuleId, 284 module_id: LocalModuleId,
269 import: &raw::ImportData, 285 import: &raw::ImportData,
270 ) -> (PerNs, ReachedFixedPoint) { 286 ) -> (PerNs, ReachedFixedPoint) {
271 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 287 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
@@ -291,9 +307,9 @@ where
291 307
292 fn record_resolved_import( 308 fn record_resolved_import(
293 &mut self, 309 &mut self,
294 module_id: CrateModuleId, 310 module_id: LocalModuleId,
295 def: PerNs, 311 def: PerNs,
296 import_id: raw::ImportId, 312 import_id: LocalImportId,
297 import: &raw::ImportData, 313 import: &raw::ImportData,
298 ) { 314 ) {
299 if import.is_glob { 315 if import.is_glob {
@@ -387,8 +403,8 @@ where
387 403
388 fn update( 404 fn update(
389 &mut self, 405 &mut self,
390 module_id: CrateModuleId, 406 module_id: LocalModuleId,
391 import: Option<raw::ImportId>, 407 import: Option<LocalImportId>,
392 resolutions: &[(Name, Resolution)], 408 resolutions: &[(Name, Resolution)],
393 ) { 409 ) {
394 self.update_recursive(module_id, import, resolutions, 0) 410 self.update_recursive(module_id, import, resolutions, 0)
@@ -396,8 +412,8 @@ where
396 412
397 fn update_recursive( 413 fn update_recursive(
398 &mut self, 414 &mut self,
399 module_id: CrateModuleId, 415 module_id: LocalModuleId,
400 import: Option<raw::ImportId>, 416 import: Option<LocalImportId>,
401 resolutions: &[(Name, Resolution)], 417 resolutions: &[(Name, Resolution)],
402 depth: usize, 418 depth: usize,
403 ) { 419 ) {
@@ -463,7 +479,7 @@ where
463 path, 479 path,
464 ); 480 );
465 481
466 if let Some(def) = resolved_res.resolved_def.get_macros() { 482 if let Some(def) = resolved_res.resolved_def.take_macros() {
467 let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id }); 483 let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id });
468 resolved.push((*module_id, call_id, def)); 484 resolved.push((*module_id, call_id, def));
469 res = ReachedFixedPoint::No; 485 res = ReachedFixedPoint::No;
@@ -484,11 +500,11 @@ where
484 500
485 fn collect_macro_expansion( 501 fn collect_macro_expansion(
486 &mut self, 502 &mut self,
487 module_id: CrateModuleId, 503 module_id: LocalModuleId,
488 macro_call_id: MacroCallId, 504 macro_call_id: MacroCallId,
489 macro_def_id: MacroDefId, 505 macro_def_id: MacroDefId,
490 ) { 506 ) {
491 if self.def_map.poison_macros.contains(&macro_def_id) { 507 if self.poison_macros.contains(&macro_def_id) {
492 return; 508 return;
493 } 509 }
494 510
@@ -508,7 +524,7 @@ where
508 .collect(raw_items.items()); 524 .collect(raw_items.items());
509 } else { 525 } else {
510 log::error!("Too deep macro expansion: {:?}", macro_call_id); 526 log::error!("Too deep macro expansion: {:?}", macro_call_id);
511 self.def_map.poison_macros.insert(macro_def_id); 527 self.poison_macros.insert(macro_def_id);
512 } 528 }
513 529
514 self.macro_stack_monitor.decrease(macro_def_id); 530 self.macro_stack_monitor.decrease(macro_def_id);
@@ -522,7 +538,7 @@ where
522/// Walks a single module, populating defs, imports and macros 538/// Walks a single module, populating defs, imports and macros
523struct ModCollector<'a, D> { 539struct ModCollector<'a, D> {
524 def_collector: D, 540 def_collector: D,
525 module_id: CrateModuleId, 541 module_id: LocalModuleId,
526 file_id: HirFileId, 542 file_id: HirFileId,
527 raw_items: &'a raw::RawItems, 543 raw_items: &'a raw::RawItems,
528 mod_dir: ModDir, 544 mod_dir: ModDir,
@@ -530,7 +546,7 @@ struct ModCollector<'a, D> {
530 546
531impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> 547impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
532where 548where
533 DB: DefDatabase2, 549 DB: DefDatabase,
534{ 550{
535 fn collect(&mut self, items: &[raw::RawItem]) { 551 fn collect(&mut self, items: &[raw::RawItem]) {
536 // Note: don't assert that inserted value is fresh: it's simply not true 552 // Note: don't assert that inserted value is fresh: it's simply not true
@@ -549,7 +565,7 @@ where
549 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 565 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
550 // any other items. 566 // any other items.
551 for item in items { 567 for item in items {
552 if self.is_cfg_enabled(item.attrs()) { 568 if self.is_cfg_enabled(&item.attrs) {
553 if let raw::RawItemKind::Import(import_id) = item.kind { 569 if let raw::RawItemKind::Import(import_id) = item.kind {
554 let import = self.raw_items[import_id].clone(); 570 let import = self.raw_items[import_id].clone();
555 if import.is_extern_crate && import.is_macro_use { 571 if import.is_extern_crate && import.is_macro_use {
@@ -560,10 +576,10 @@ where
560 } 576 }
561 577
562 for item in items { 578 for item in items {
563 if self.is_cfg_enabled(item.attrs()) { 579 if self.is_cfg_enabled(&item.attrs) {
564 match item.kind { 580 match item.kind {
565 raw::RawItemKind::Module(m) => { 581 raw::RawItemKind::Module(m) => {
566 self.collect_module(&self.raw_items[m], item.attrs()) 582 self.collect_module(&self.raw_items[m], &item.attrs)
567 } 583 }
568 raw::RawItemKind::Import(import_id) => self 584 raw::RawItemKind::Import(import_id) => self
569 .def_collector 585 .def_collector
@@ -585,9 +601,9 @@ where
585 } 601 }
586 } 602 }
587 603
588 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) { 604 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
589 let path_attr = self.path_attr(attrs); 605 let path_attr = attrs.by_key("path").string_value();
590 let is_macro_use = self.is_macro_use(attrs); 606 let is_macro_use = attrs.by_key("macro_use").exists();
591 match module { 607 match module {
592 // inline module, just recurse 608 // inline module, just recurse
593 raw::ModuleData::Definition { name, items, ast_id } => { 609 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -647,7 +663,7 @@ where
647 name: Name, 663 name: Name,
648 declaration: AstId<ast::Module>, 664 declaration: AstId<ast::Module>,
649 definition: Option<FileId>, 665 definition: Option<FileId>,
650 ) -> CrateModuleId { 666 ) -> LocalModuleId {
651 let modules = &mut self.def_collector.def_map.modules; 667 let modules = &mut self.def_collector.def_map.modules;
652 let res = modules.alloc(ModuleData::default()); 668 let res = modules.alloc(ModuleData::default());
653 modules[res].parent = Some(self.module_id); 669 modules[res].parent = Some(self.module_id);
@@ -702,7 +718,10 @@ where
702 PerNs::values(def.into()) 718 PerNs::values(def.into())
703 } 719 }
704 raw::DefKind::Static(ast_id) => { 720 raw::DefKind::Static(ast_id) => {
705 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) 721 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
722 .intern(self.def_collector.db);
723
724 PerNs::values(def.into())
706 } 725 }
707 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 726 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
708 raw::DefKind::TypeAlias(ast_id) => { 727 raw::DefKind::TypeAlias(ast_id) => {
@@ -772,23 +791,19 @@ where
772 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); 791 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
773 } 792 }
774 793
775 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { 794 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
776 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); 795 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
777 for (name, macro_) in macros { 796 for (name, macro_) in macros {
778 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); 797 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
779 } 798 }
780 } 799 }
781 800
782 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { 801 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
783 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 802 // FIXME: handle cfg_attr :-)
784 } 803 attrs
785 804 .by_key("cfg")
786 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> { 805 .tt_values()
787 attrs.iter().find_map(|attr| attr.as_path()) 806 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
788 }
789
790 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
791 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
792 } 807 }
793} 808}
794 809
@@ -802,15 +817,15 @@ mod tests {
802 use ra_db::{fixture::WithFixture, SourceDatabase}; 817 use ra_db::{fixture::WithFixture, SourceDatabase};
803 use rustc_hash::FxHashSet; 818 use rustc_hash::FxHashSet;
804 819
805 use crate::{db::DefDatabase2, test_db::TestDB}; 820 use crate::{db::DefDatabase, test_db::TestDB};
806 821
807 use super::*; 822 use super::*;
808 823
809 fn do_collect_defs( 824 fn do_collect_defs(
810 db: &impl DefDatabase2, 825 db: &impl DefDatabase,
811 def_map: CrateDefMap, 826 def_map: CrateDefMap,
812 monitor: MacroStackMonitor, 827 monitor: MacroStackMonitor,
813 ) -> CrateDefMap { 828 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
814 let mut collector = DefCollector { 829 let mut collector = DefCollector {
815 db, 830 db,
816 def_map, 831 def_map,
@@ -819,19 +834,24 @@ mod tests {
819 unexpanded_macros: Vec::new(), 834 unexpanded_macros: Vec::new(),
820 mod_dirs: FxHashMap::default(), 835 mod_dirs: FxHashMap::default(),
821 macro_stack_monitor: monitor, 836 macro_stack_monitor: monitor,
837 poison_macros: FxHashSet::default(),
822 cfg_options: &CfgOptions::default(), 838 cfg_options: &CfgOptions::default(),
823 }; 839 };
824 collector.collect(); 840 collector.collect();
825 collector.finish() 841 (collector.def_map, collector.poison_macros)
826 } 842 }
827 843
828 fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { 844 fn do_limited_resolve(
845 code: &str,
846 limit: u32,
847 poison_limit: u32,
848 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
829 let (db, _file_id) = TestDB::with_single_file(&code); 849 let (db, _file_id) = TestDB::with_single_file(&code);
830 let krate = db.test_crate(); 850 let krate = db.test_crate();
831 851
832 let def_map = { 852 let def_map = {
833 let edition = db.crate_graph().edition(krate); 853 let edition = db.crate_graph().edition(krate);
834 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 854 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
835 let root = modules.alloc(ModuleData::default()); 855 let root = modules.alloc(ModuleData::default());
836 CrateDefMap { 856 CrateDefMap {
837 krate, 857 krate,
@@ -840,7 +860,6 @@ mod tests {
840 prelude: None, 860 prelude: None,
841 root, 861 root,
842 modules, 862 modules,
843 poison_macros: FxHashSet::default(),
844 diagnostics: Vec::new(), 863 diagnostics: Vec::new(),
845 } 864 }
846 }; 865 };
@@ -870,7 +889,7 @@ foo!(KABOOM);
870 889
871 #[test] 890 #[test]
872 fn test_macro_expand_poisoned() { 891 fn test_macro_expand_poisoned() {
873 let def = do_limited_resolve( 892 let (_, poison_macros) = do_limited_resolve(
874 r#" 893 r#"
875 macro_rules! foo { 894 macro_rules! foo {
876 ($ty:ty) => { foo!($ty); } 895 ($ty:ty) => { foo!($ty); }
@@ -881,12 +900,12 @@ foo!(KABOOM);
881 16, 900 16,
882 ); 901 );
883 902
884 assert_eq!(def.poison_macros.len(), 1); 903 assert_eq!(poison_macros.len(), 1);
885 } 904 }
886 905
887 #[test] 906 #[test]
888 fn test_macro_expand_normal() { 907 fn test_macro_expand_normal() {
889 let def = do_limited_resolve( 908 let (_, poison_macros) = do_limited_resolve(
890 r#" 909 r#"
891 macro_rules! foo { 910 macro_rules! foo {
892 ($ident:ident) => { struct $ident {} } 911 ($ident:ident) => { struct $ident {} }
@@ -897,6 +916,6 @@ foo!(Bar);
897 16, 916 16,
898 ); 917 );
899 918
900 assert_eq!(def.poison_macros.len(), 0); 919 assert_eq!(poison_macros.len(), 0);
901 } 920 }
902} 921}
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index b3b1379d0..14fb8ba3a 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -3,7 +3,7 @@ use hir_expand::name::Name;
3use ra_db::{FileId, RelativePathBuf}; 3use ra_db::{FileId, RelativePathBuf};
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
5 5
6use crate::{db::DefDatabase2, HirFileId}; 6use crate::{db::DefDatabase, HirFileId};
7 7
8#[derive(Clone, Debug)] 8#[derive(Clone, Debug)]
9pub(super) struct ModDir { 9pub(super) struct ModDir {
@@ -40,7 +40,7 @@ impl ModDir {
40 40
41 pub(super) fn resolve_declaration( 41 pub(super) fn resolve_declaration(
42 &self, 42 &self,
43 db: &impl DefDatabase2, 43 db: &impl DefDatabase,
44 file_id: HirFileId, 44 file_id: HirFileId,
45 name: &Name, 45 name: &Name,
46 attr_path: Option<&SmolStr>, 46 attr_path: Option<&SmolStr>,
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 95692f826..9455f22bb 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -15,10 +15,11 @@ use ra_db::Edition;
15use test_utils::tested_by; 15use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 db::DefDatabase2, 18 db::DefDatabase,
19 nameres::{per_ns::PerNs, CrateDefMap}, 19 nameres::CrateDefMap,
20 path::{Path, PathKind}, 20 path::{Path, PathKind},
21 AdtId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId, 21 per_ns::PerNs,
22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
22}; 23};
23 24
24#[derive(Debug, Clone, Copy, PartialEq, Eq)] 25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,9 +64,9 @@ impl CrateDefMap {
63 // the result. 64 // the result.
64 pub(super) fn resolve_path_fp_with_macro( 65 pub(super) fn resolve_path_fp_with_macro(
65 &self, 66 &self,
66 db: &impl DefDatabase2, 67 db: &impl DefDatabase,
67 mode: ResolveMode, 68 mode: ResolveMode,
68 original_module: CrateModuleId, 69 original_module: LocalModuleId,
69 path: &Path, 70 path: &Path,
70 ) -> ResolvePathResult { 71 ) -> ResolvePathResult {
71 let mut segments = path.segments.iter().enumerate(); 72 let mut segments = path.segments.iter().enumerate();
@@ -216,8 +217,8 @@ impl CrateDefMap {
216 217
217 fn resolve_name_in_module( 218 fn resolve_name_in_module(
218 &self, 219 &self,
219 db: &impl DefDatabase2, 220 db: &impl DefDatabase,
220 module: CrateModuleId, 221 module: LocalModuleId,
221 name: &Name, 222 name: &Name,
222 ) -> PerNs { 223 ) -> PerNs {
223 // Resolve in: 224 // Resolve in:
@@ -243,7 +244,7 @@ impl CrateDefMap {
243 from_crate_root.or(from_extern_prelude) 244 from_crate_root.or(from_extern_prelude)
244 } 245 }
245 246
246 fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs { 247 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
247 if let Some(prelude) = self.prelude { 248 if let Some(prelude) = self.prelude {
248 let keep; 249 let keep;
249 let def_map = if prelude.krate == self.krate { 250 let def_map = if prelude.krate == self.krate {
diff --git a/crates/ra_hir_def/src/nameres/per_ns.rs b/crates/ra_hir_def/src/nameres/per_ns.rs
deleted file mode 100644
index 717ed1ef9..000000000
--- a/crates/ra_hir_def/src/nameres/per_ns.rs
+++ /dev/null
@@ -1,74 +0,0 @@
1//! FIXME: write short doc here
2
3use hir_expand::MacroDefId;
4
5use crate::ModuleDefId;
6
7#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub struct PerNs {
9 pub types: Option<ModuleDefId>,
10 pub values: Option<ModuleDefId>,
11 /// Since macros has different type, many methods simply ignore it.
12 /// We can only use special method like `get_macros` to access it.
13 pub macros: Option<MacroDefId>,
14}
15
16impl Default for PerNs {
17 fn default() -> Self {
18 PerNs { types: None, values: None, macros: None }
19 }
20}
21
22impl PerNs {
23 pub fn none() -> PerNs {
24 PerNs { types: None, values: None, macros: None }
25 }
26
27 pub fn values(t: ModuleDefId) -> PerNs {
28 PerNs { types: None, values: Some(t), macros: None }
29 }
30
31 pub fn types(t: ModuleDefId) -> PerNs {
32 PerNs { types: Some(t), values: None, macros: None }
33 }
34
35 pub fn both(types: ModuleDefId, values: ModuleDefId) -> PerNs {
36 PerNs { types: Some(types), values: Some(values), macros: None }
37 }
38
39 pub fn macros(macro_: MacroDefId) -> PerNs {
40 PerNs { types: None, values: None, macros: Some(macro_) }
41 }
42
43 pub fn is_none(&self) -> bool {
44 self.types.is_none() && self.values.is_none() && self.macros.is_none()
45 }
46
47 pub fn is_all(&self) -> bool {
48 self.types.is_some() && self.values.is_some() && self.macros.is_some()
49 }
50
51 pub fn take_types(self) -> Option<ModuleDefId> {
52 self.types
53 }
54
55 pub fn take_values(self) -> Option<ModuleDefId> {
56 self.values
57 }
58
59 pub fn get_macros(&self) -> Option<MacroDefId> {
60 self.macros
61 }
62
63 pub fn only_macros(&self) -> PerNs {
64 PerNs { types: None, values: None, macros: self.macros }
65 }
66
67 pub fn or(self, other: PerNs) -> PerNs {
68 PerNs {
69 types: self.types.or(other.types),
70 values: self.values.or(other.values),
71 macros: self.macros.or(other.macros),
72 }
73 }
74}
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 7c68fd638..401af031c 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -1,4 +1,9 @@
1//! FIXME: write short doc here 1//! Lowers syntax tree of a rust file into a raw representation of containing
2//! items, *without* attaching them to a module structure.
3//!
4//! That is, raw items don't have semantics, just as syntax, but, unlike syntax,
5//! they don't change with trivial source code edits, making them a great tool
6//! for building salsa recomputation firewalls.
2 7
3use std::{ops::Index, sync::Arc}; 8use std::{ops::Index, sync::Arc};
4 9
@@ -12,11 +17,14 @@ use hir_expand::{
12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 17use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
13use ra_syntax::{ 18use ra_syntax::{
14 ast::{self, AttrsOwner, NameOwner}, 19 ast::{self, AttrsOwner, NameOwner},
15 AstNode, AstPtr, SourceFile, 20 AstNode, AstPtr,
16}; 21};
17use test_utils::tested_by; 22use test_utils::tested_by;
18 23
19use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source}; 24use crate::{
25 attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, LocalImportId,
26 Source,
27};
20 28
21/// `RawItems` is a set of top-level items in a file (except for impls). 29/// `RawItems` is a set of top-level items in a file (except for impls).
22/// 30///
@@ -25,7 +33,7 @@ use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, Modu
25#[derive(Debug, Default, PartialEq, Eq)] 33#[derive(Debug, Default, PartialEq, Eq)]
26pub struct RawItems { 34pub struct RawItems {
27 modules: Arena<Module, ModuleData>, 35 modules: Arena<Module, ModuleData>,
28 imports: Arena<ImportId, ImportData>, 36 imports: Arena<LocalImportId, ImportData>,
29 defs: Arena<Def, DefData>, 37 defs: Arena<Def, DefData>,
30 macros: Arena<Macro, MacroData>, 38 macros: Arena<Macro, MacroData>,
31 impls: Arena<Impl, ImplData>, 39 impls: Arena<Impl, ImplData>,
@@ -35,47 +43,33 @@ pub struct RawItems {
35 43
36#[derive(Debug, Default, PartialEq, Eq)] 44#[derive(Debug, Default, PartialEq, Eq)]
37pub struct ImportSourceMap { 45pub struct ImportSourceMap {
38 map: ArenaMap<ImportId, ImportSourcePtr>, 46 map: ArenaMap<LocalImportId, ImportSourcePtr>,
39} 47}
40 48
41type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; 49type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
42type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
43
44fn to_node(ptr: ImportSourcePtr, file: &SourceFile) -> ImportSource {
45 ptr.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
46}
47 50
48impl ImportSourceMap { 51impl ImportSourceMap {
49 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 52 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr {
50 self.map.insert(import, ptr) 53 self.map[import].clone()
51 }
52
53 pub fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource {
54 let file = match source {
55 ModuleSource::SourceFile(file) => file.clone(),
56 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
57 };
58
59 to_node(self.map[import], &file)
60 } 54 }
61} 55}
62 56
63impl RawItems { 57impl RawItems {
64 pub(crate) fn raw_items_query( 58 pub(crate) fn raw_items_query(
65 db: &(impl DefDatabase2 + AstDatabase), 59 db: &(impl DefDatabase + AstDatabase),
66 file_id: HirFileId, 60 file_id: HirFileId,
67 ) -> Arc<RawItems> { 61 ) -> Arc<RawItems> {
68 db.raw_items_with_source_map(file_id).0 62 db.raw_items_with_source_map(file_id).0
69 } 63 }
70 64
71 pub(crate) fn raw_items_with_source_map_query( 65 pub(crate) fn raw_items_with_source_map_query(
72 db: &(impl DefDatabase2 + AstDatabase), 66 db: &(impl DefDatabase + AstDatabase),
73 file_id: HirFileId, 67 file_id: HirFileId,
74 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 68 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
75 let mut collector = RawItemsCollector { 69 let mut collector = RawItemsCollector {
76 raw_items: RawItems::default(), 70 raw_items: RawItems::default(),
77 source_ast_id_map: db.ast_id_map(file_id), 71 source_ast_id_map: db.ast_id_map(file_id),
78 source_map: ImportSourceMap::default(), 72 imports: Trace::new(),
79 file_id, 73 file_id,
80 hygiene: Hygiene::new(db, file_id), 74 hygiene: Hygiene::new(db, file_id),
81 }; 75 };
@@ -86,7 +80,11 @@ impl RawItems {
86 collector.process_module(None, item_list); 80 collector.process_module(None, item_list);
87 } 81 }
88 } 82 }
89 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 83 let mut raw_items = collector.raw_items;
84 let (arena, map) = collector.imports.into_arena_and_map();
85 raw_items.imports = arena;
86 let source_map = ImportSourceMap { map };
87 (Arc::new(raw_items), Arc::new(source_map))
90 } 88 }
91 89
92 pub(super) fn items(&self) -> &[RawItem] { 90 pub(super) fn items(&self) -> &[RawItem] {
@@ -101,9 +99,9 @@ impl Index<Module> for RawItems {
101 } 99 }
102} 100}
103 101
104impl Index<ImportId> for RawItems { 102impl Index<LocalImportId> for RawItems {
105 type Output = ImportData; 103 type Output = ImportData;
106 fn index(&self, idx: ImportId) -> &ImportData { 104 fn index(&self, idx: LocalImportId) -> &ImportData {
107 &self.imports[idx] 105 &self.imports[idx]
108 } 106 }
109} 107}
@@ -129,25 +127,16 @@ impl Index<Impl> for RawItems {
129 } 127 }
130} 128}
131 129
132// Avoid heap allocation on items without attributes.
133type Attrs = Option<Arc<[Attr]>>;
134
135#[derive(Debug, PartialEq, Eq, Clone)] 130#[derive(Debug, PartialEq, Eq, Clone)]
136pub(super) struct RawItem { 131pub(super) struct RawItem {
137 attrs: Attrs, 132 pub(super) attrs: Attrs,
138 pub(super) kind: RawItemKind, 133 pub(super) kind: RawItemKind,
139} 134}
140 135
141impl RawItem {
142 pub(super) fn attrs(&self) -> &[Attr] {
143 self.attrs.as_ref().map_or(&[], |it| &*it)
144 }
145}
146
147#[derive(Debug, PartialEq, Eq, Clone, Copy)] 136#[derive(Debug, PartialEq, Eq, Clone, Copy)]
148pub(super) enum RawItemKind { 137pub(super) enum RawItemKind {
149 Module(Module), 138 Module(Module),
150 Import(ImportId), 139 Import(LocalImportId),
151 Def(Def), 140 Def(Def),
152 Macro(Macro), 141 Macro(Macro),
153 Impl(Impl), 142 Impl(Impl),
@@ -163,10 +152,6 @@ pub(super) enum ModuleData {
163 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 152 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
164} 153}
165 154
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub struct ImportId(RawId);
168impl_arena_id!(ImportId);
169
170#[derive(Debug, Clone, PartialEq, Eq)] 155#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct ImportData { 156pub struct ImportData {
172 pub(super) path: Path, 157 pub(super) path: Path,
@@ -223,8 +208,8 @@ pub(super) struct ImplData {
223 208
224struct RawItemsCollector { 209struct RawItemsCollector {
225 raw_items: RawItems, 210 raw_items: RawItems,
211 imports: Trace<LocalImportId, ImportData, ImportSourcePtr>,
226 source_ast_id_map: Arc<AstIdMap>, 212 source_ast_id_map: Arc<AstIdMap>,
227 source_map: ImportSourceMap,
228 file_id: HirFileId, 213 file_id: HirFileId,
229 hygiene: Hygiene, 214 hygiene: Hygiene,
230} 215}
@@ -408,8 +393,7 @@ impl RawItemsCollector {
408 data: ImportData, 393 data: ImportData,
409 source: ImportSourcePtr, 394 source: ImportSourcePtr,
410 ) { 395 ) {
411 let import = self.raw_items.imports.alloc(data); 396 let import = self.imports.alloc(|| source, || data);
412 self.source_map.insert(import, source);
413 self.push_item(current_module, attrs, RawItemKind::Import(import)) 397 self.push_item(current_module, attrs, RawItemKind::Import(import))
414 } 398 }
415 399
@@ -425,6 +409,6 @@ impl RawItemsCollector {
425 } 409 }
426 410
427 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 411 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
428 Attr::from_attrs_owner(item, &self.hygiene) 412 Attrs::new(item, &self.hygiene)
429 } 413 }
430} 414}
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 256f7d4be..f502f1cb3 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -10,7 +10,7 @@ use insta::assert_snapshot;
10use ra_db::{fixture::WithFixture, SourceDatabase}; 10use ra_db::{fixture::WithFixture, SourceDatabase};
11use test_utils::covers; 11use test_utils::covers;
12 12
13use crate::{db::DefDatabase2, nameres::*, test_db::TestDB, CrateModuleId}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId};
14 14
15fn def_map(fixtute: &str) -> String { 15fn def_map(fixtute: &str) -> String {
16 let dm = compute_crate_def_map(fixtute); 16 let dm = compute_crate_def_map(fixtute);
@@ -25,10 +25,10 @@ fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
25 25
26fn render_crate_def_map(map: &CrateDefMap) -> String { 26fn render_crate_def_map(map: &CrateDefMap) -> String {
27 let mut buf = String::new(); 27 let mut buf = String::new();
28 go(&mut buf, map, "\ncrate", map.root()); 28 go(&mut buf, map, "\ncrate", map.root);
29 return buf.trim().to_string(); 29 return buf.trim().to_string();
30 30
31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) { 31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
32 *buf += path; 32 *buf += path;
33 *buf += "\n"; 33 *buf += "\n";
34 34
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index eb7b85c07..e11530062 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -665,7 +665,7 @@ fn unresolved_module_diagnostics() {
665 @r###" 665 @r###"
666 [ 666 [
667 UnresolvedModule { 667 UnresolvedModule {
668 module: CrateModuleId( 668 module: LocalModuleId(
669 0, 669 0,
670 ), 670 ),
671 declaration: AstId { 671 declaration: AstId {