aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r--crates/hir_def/src/nameres/collector.rs212
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs163
-rw-r--r--crates/hir_def/src/nameres/tests.rs15
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs16
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs14
5 files changed, 294 insertions, 126 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 0cd61698c..e51d89b43 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -24,38 +24,43 @@ use tt::{Leaf, TokenTree};
24use crate::{ 24use crate::{
25 attr::Attrs, 25 attr::Attrs,
26 db::DefDatabase, 26 db::DefDatabase,
27 item_attr_as_call_id,
27 item_scope::{ImportType, PerNsGlobImports}, 28 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{ 29 item_tree::{
29 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, 30 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind,
30 StructDefKind, 31 StructDefKind,
31 }, 32 },
33 macro_call_as_call_id,
32 nameres::{ 34 nameres::{
33 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 35 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
34 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 36 BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
35 }, 37 },
36 path::{ImportAlias, ModPath, PathKind}, 38 path::{ImportAlias, ModPath, PathKind},
37 per_ns::PerNs, 39 per_ns::PerNs,
38 visibility::{RawVisibility, Visibility}, 40 visibility::{RawVisibility, Visibility},
39 AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, 41 AdtId, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc,
40 FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, 42 ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc,
41 TraitLoc, TypeAliasLoc, UnionLoc, 43 UnionLoc, UnresolvedMacro,
42}; 44};
43 45
44const GLOB_RECURSION_LIMIT: usize = 100; 46const GLOB_RECURSION_LIMIT: usize = 100;
45const EXPANSION_DEPTH_LIMIT: usize = 128; 47const EXPANSION_DEPTH_LIMIT: usize = 128;
46const FIXED_POINT_LIMIT: usize = 8192; 48const FIXED_POINT_LIMIT: usize = 8192;
47 49
48pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 50pub(super) fn collect_defs(
51 db: &dyn DefDatabase,
52 mut def_map: DefMap,
53 block: Option<AstId<ast::BlockExpr>>,
54) -> DefMap {
49 let crate_graph = db.crate_graph(); 55 let crate_graph = db.crate_graph();
50 56
51 // populate external prelude 57 // populate external prelude
52 for dep in &crate_graph[def_map.krate].dependencies { 58 for dep in &crate_graph[def_map.krate].dependencies {
53 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); 59 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
54 let dep_def_map = db.crate_def_map(dep.crate_id); 60 let dep_def_map = db.crate_def_map(dep.crate_id);
55 def_map.extern_prelude.insert( 61 def_map
56 dep.as_name(), 62 .extern_prelude
57 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), 63 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
58 );
59 64
60 // look for the prelude 65 // look for the prelude
61 // If the dependency defines a prelude, we overwrite an already defined 66 // If the dependency defines a prelude, we overwrite an already defined
@@ -93,6 +98,14 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
93 exports_proc_macros: false, 98 exports_proc_macros: false,
94 from_glob_import: Default::default(), 99 from_glob_import: Default::default(),
95 }; 100 };
101 match block {
102 Some(block) => {
103 collector.seed_with_inner(block);
104 }
105 None => {
106 collector.seed_with_top_level();
107 }
108 }
96 collector.collect(); 109 collector.collect();
97 collector.finish() 110 collector.finish()
98} 111}
@@ -210,7 +223,7 @@ struct DefData<'a> {
210/// Walks the tree of module recursively 223/// Walks the tree of module recursively
211struct DefCollector<'a> { 224struct DefCollector<'a> {
212 db: &'a dyn DefDatabase, 225 db: &'a dyn DefDatabase,
213 def_map: CrateDefMap, 226 def_map: DefMap,
214 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, 227 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
215 unresolved_imports: Vec<ImportDirective>, 228 unresolved_imports: Vec<ImportDirective>,
216 resolved_imports: Vec<ImportDirective>, 229 resolved_imports: Vec<ImportDirective>,
@@ -228,7 +241,7 @@ struct DefCollector<'a> {
228} 241}
229 242
230impl DefCollector<'_> { 243impl DefCollector<'_> {
231 fn collect(&mut self) { 244 fn seed_with_top_level(&mut self) {
232 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; 245 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
233 let item_tree = self.db.item_tree(file_id.into()); 246 let item_tree = self.db.item_tree(file_id.into());
234 let module_id = self.def_map.root; 247 let module_id = self.def_map.root;
@@ -248,7 +261,30 @@ impl DefCollector<'_> {
248 } 261 }
249 .collect(item_tree.top_level_items()); 262 .collect(item_tree.top_level_items());
250 } 263 }
264 }
251 265
266 fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) {
267 let item_tree = self.db.item_tree(block.file_id);
268 let module_id = self.def_map.root;
269 self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block };
270 if item_tree
271 .top_level_attrs(self.db, self.def_map.krate)
272 .cfg()
273 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
274 {
275 ModCollector {
276 def_collector: &mut *self,
277 macro_depth: 0,
278 module_id,
279 file_id: block.file_id,
280 item_tree: &item_tree,
281 mod_dir: ModDir::root(),
282 }
283 .collect(item_tree.inner_items_of_block(block.value));
284 }
285 }
286
287 fn collect(&mut self) {
252 // main name resolution fixed-point loop. 288 // main name resolution fixed-point loop.
253 let mut i = 0; 289 let mut i = 0;
254 loop { 290 loop {
@@ -296,11 +332,9 @@ impl DefCollector<'_> {
296 // exported in type/value namespace. This function reduces the visibility of all items 332 // exported in type/value namespace. This function reduces the visibility of all items
297 // in the crate root that aren't proc macros. 333 // in the crate root that aren't proc macros.
298 let root = self.def_map.root; 334 let root = self.def_map.root;
335 let module_id = self.def_map.module_id(root);
299 let root = &mut self.def_map.modules[root]; 336 let root = &mut self.def_map.modules[root];
300 root.scope.censor_non_proc_macros(ModuleId { 337 root.scope.censor_non_proc_macros(module_id);
301 krate: self.def_map.krate,
302 local_id: self.def_map.root,
303 });
304 } 338 }
305 } 339 }
306 340
@@ -542,7 +576,7 @@ impl DefCollector<'_> {
542 } else if m.krate != self.def_map.krate { 576 } else if m.krate != self.def_map.krate {
543 mark::hit!(glob_across_crates); 577 mark::hit!(glob_across_crates);
544 // glob import from other crate => we can just import everything once 578 // glob import from other crate => we can just import everything once
545 let item_map = self.db.crate_def_map(m.krate); 579 let item_map = m.def_map(self.db);
546 let scope = &item_map[m.local_id].scope; 580 let scope = &item_map[m.local_id].scope;
547 581
548 // Module scoped macros is included 582 // Module scoped macros is included
@@ -560,7 +594,13 @@ impl DefCollector<'_> {
560 // glob import from same crate => we do an initial 594 // glob import from same crate => we do an initial
561 // import, and then need to propagate any further 595 // import, and then need to propagate any further
562 // additions 596 // additions
563 let scope = &self.def_map[m.local_id].scope; 597 let def_map;
598 let scope = if m.block == self.def_map.block_id() {
599 &self.def_map[m.local_id].scope
600 } else {
601 def_map = m.def_map(self.db);
602 &def_map[m.local_id].scope
603 };
564 604
565 // Module scoped macros is included 605 // Module scoped macros is included
566 let items = scope 606 let items = scope
@@ -570,7 +610,7 @@ impl DefCollector<'_> {
570 ( 610 (
571 n, 611 n,
572 res.filter_visibility(|v| { 612 res.filter_visibility(|v| {
573 v.is_visible_from_def_map(&self.def_map, module_id) 613 v.is_visible_from_def_map(self.db, &self.def_map, module_id)
574 }), 614 }),
575 ) 615 )
576 }) 616 })
@@ -617,7 +657,7 @@ impl DefCollector<'_> {
617 } 657 }
618 } 658 }
619 } else { 659 } else {
620 match import.path.segments.last() { 660 match import.path.segments().last() {
621 Some(last_segment) => { 661 Some(last_segment) => {
622 let name = match &import.alias { 662 let name = match &import.alias {
623 Some(ImportAlias::Alias(name)) => Some(name.clone()), 663 Some(ImportAlias::Alias(name)) => Some(name.clone()),
@@ -723,7 +763,7 @@ impl DefCollector<'_> {
723 .filter(|(glob_importing_module, _)| { 763 .filter(|(glob_importing_module, _)| {
724 // we know all resolutions have the same visibility (`vis`), so we 764 // we know all resolutions have the same visibility (`vis`), so we
725 // just need to check that once 765 // just need to check that once
726 vis.is_visible_from_def_map(&self.def_map, *glob_importing_module) 766 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
727 }) 767 })
728 .cloned() 768 .cloned()
729 .collect::<Vec<_>>(); 769 .collect::<Vec<_>>();
@@ -752,8 +792,11 @@ impl DefCollector<'_> {
752 return false; 792 return false;
753 } 793 }
754 794
755 if let Some(call_id) = 795 match macro_call_as_call_id(
756 directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { 796 &directive.ast_id,
797 self.db,
798 self.def_map.krate,
799 |path| {
757 let resolved_res = self.def_map.resolve_path_fp_with_macro( 800 let resolved_res = self.def_map.resolve_path_fp_with_macro(
758 self.db, 801 self.db,
759 ResolveMode::Other, 802 ResolveMode::Other,
@@ -762,24 +805,29 @@ impl DefCollector<'_> {
762 BuiltinShadowMode::Module, 805 BuiltinShadowMode::Module,
763 ); 806 );
764 resolved_res.resolved_def.take_macros() 807 resolved_res.resolved_def.take_macros()
765 }) 808 },
766 { 809 &mut |_err| (),
767 resolved.push((directive.module_id, call_id, directive.depth)); 810 ) {
768 res = ReachedFixedPoint::No; 811 Ok(Ok(call_id)) => {
769 return false; 812 resolved.push((directive.module_id, call_id, directive.depth));
813 res = ReachedFixedPoint::No;
814 return false;
815 }
816 Err(UnresolvedMacro) | Ok(Err(_)) => {}
770 } 817 }
771 818
772 true 819 true
773 }); 820 });
774 attribute_macros.retain(|directive| { 821 attribute_macros.retain(|directive| {
775 if let Some(call_id) = 822 match item_attr_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| {
776 directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| { 823 self.resolve_attribute_macro(&directive, &path)
777 self.resolve_attribute_macro(&directive, &path) 824 }) {
778 }) 825 Ok(call_id) => {
779 { 826 resolved.push((directive.module_id, call_id, 0));
780 resolved.push((directive.module_id, call_id, 0)); 827 res = ReachedFixedPoint::No;
781 res = ReachedFixedPoint::No; 828 return false;
782 return false; 829 }
830 Err(UnresolvedMacro) => (),
783 } 831 }
784 832
785 true 833 true
@@ -859,12 +907,13 @@ impl DefCollector<'_> {
859 .collect(item_tree.top_level_items()); 907 .collect(item_tree.top_level_items());
860 } 908 }
861 909
862 fn finish(mut self) -> CrateDefMap { 910 fn finish(mut self) -> DefMap {
863 // Emit diagnostics for all remaining unexpanded macros. 911 // Emit diagnostics for all remaining unexpanded macros.
864 912
865 for directive in &self.unexpanded_macros { 913 for directive in &self.unexpanded_macros {
866 let mut error = None; 914 let mut error = None;
867 directive.ast_id.as_call_id_with_errors( 915 match macro_call_as_call_id(
916 &directive.ast_id,
868 self.db, 917 self.db,
869 self.def_map.krate, 918 self.def_map.krate,
870 |path| { 919 |path| {
@@ -880,15 +929,15 @@ impl DefCollector<'_> {
880 &mut |e| { 929 &mut |e| {
881 error.get_or_insert(e); 930 error.get_or_insert(e);
882 }, 931 },
883 ); 932 ) {
884 933 Ok(_) => (),
885 if let Some(err) = error { 934 Err(UnresolvedMacro) => {
886 self.def_map.diagnostics.push(DefDiagnostic::macro_error( 935 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
887 directive.module_id, 936 directive.module_id,
888 MacroCallKind::FnLike(directive.ast_id.ast_id), 937 directive.ast_id.ast_id,
889 err.to_string(), 938 ));
890 )); 939 }
891 } 940 };
892 } 941 }
893 942
894 // Emit diagnostics for all remaining unresolved imports. 943 // Emit diagnostics for all remaining unresolved imports.
@@ -918,7 +967,7 @@ impl DefCollector<'_> {
918 let item_tree = self.db.item_tree(import.file_id); 967 let item_tree = self.db.item_tree(import.file_id);
919 let import_data = &item_tree[import.value]; 968 let import_data = &item_tree[import.value];
920 969
921 match (import_data.path.segments.first(), &import_data.path.kind) { 970 match (import_data.path.segments().first(), &import_data.path.kind) {
922 (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => { 971 (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => {
923 if diagnosed_extern_crates.contains(krate) { 972 if diagnosed_extern_crates.contains(krate) {
924 continue; 973 continue;
@@ -993,8 +1042,7 @@ impl ModCollector<'_, '_> {
993 continue; 1042 continue;
994 } 1043 }
995 } 1044 }
996 let module = 1045 let module = self.def_collector.def_map.module_id(self.module_id);
997 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
998 let container = ContainerId::ModuleId(module); 1046 let container = ContainerId::ModuleId(module);
999 1047
1000 let mut def = None; 1048 let mut def = None;
@@ -1061,10 +1109,7 @@ impl ModCollector<'_, '_> {
1061 } 1109 }
1062 } 1110 }
1063 ModItem::Impl(imp) => { 1111 ModItem::Impl(imp) => {
1064 let module = ModuleId { 1112 let module = self.def_collector.def_map.module_id(self.module_id);
1065 krate: self.def_collector.def_map.krate,
1066 local_id: self.module_id,
1067 };
1068 let container = ContainerId::ModuleId(module); 1113 let container = ContainerId::ModuleId(module);
1069 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } 1114 let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) }
1070 .intern(self.def_collector.db); 1115 .intern(self.def_collector.db);
@@ -1245,12 +1290,8 @@ impl ModCollector<'_, '_> {
1245 // out of line module, resolve, parse and recurse 1290 // out of line module, resolve, parse and recurse
1246 ModKind::Outline {} => { 1291 ModKind::Outline {} => {
1247 let ast_id = AstId::new(self.file_id, module.ast_id); 1292 let ast_id = AstId::new(self.file_id, module.ast_id);
1248 match self.mod_dir.resolve_declaration( 1293 let db = self.def_collector.db;
1249 self.def_collector.db, 1294 match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) {
1250 self.file_id,
1251 &module.name,
1252 path_attr,
1253 ) {
1254 Ok((file_id, is_mod_rs, mod_dir)) => { 1295 Ok((file_id, is_mod_rs, mod_dir)) => {
1255 let module_id = self.push_child_module( 1296 let module_id = self.push_child_module(
1256 module.name.clone(), 1297 module.name.clone(),
@@ -1258,7 +1299,7 @@ impl ModCollector<'_, '_> {
1258 Some((file_id, is_mod_rs)), 1299 Some((file_id, is_mod_rs)),
1259 &self.item_tree[module.visibility], 1300 &self.item_tree[module.visibility],
1260 ); 1301 );
1261 let item_tree = self.def_collector.db.item_tree(file_id.into()); 1302 let item_tree = db.item_tree(file_id.into());
1262 ModCollector { 1303 ModCollector {
1263 def_collector: &mut *self.def_collector, 1304 def_collector: &mut *self.def_collector,
1264 macro_depth: self.macro_depth, 1305 macro_depth: self.macro_depth,
@@ -1268,7 +1309,12 @@ impl ModCollector<'_, '_> {
1268 mod_dir, 1309 mod_dir,
1269 } 1310 }
1270 .collect(item_tree.top_level_items()); 1311 .collect(item_tree.top_level_items());
1271 if is_macro_use { 1312 if is_macro_use
1313 || item_tree
1314 .top_level_attrs(db, self.def_collector.def_map.krate)
1315 .by_key("macro_use")
1316 .exists()
1317 {
1272 self.import_all_legacy_macros(module_id); 1318 self.import_all_legacy_macros(module_id);
1273 } 1319 }
1274 } 1320 }
@@ -1307,7 +1353,7 @@ impl ModCollector<'_, '_> {
1307 modules[res].scope.define_legacy_macro(name, mac) 1353 modules[res].scope.define_legacy_macro(name, mac)
1308 } 1354 }
1309 modules[self.module_id].children.insert(name.clone(), res); 1355 modules[self.module_id].children.insert(name.clone(), res);
1310 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; 1356 let module = self.def_collector.def_map.module_id(res);
1311 let def: ModuleDefId = module.into(); 1357 let def: ModuleDefId = module.into();
1312 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 1358 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
1313 self.def_collector.update( 1359 self.def_collector.update(
@@ -1411,13 +1457,21 @@ impl ModCollector<'_, '_> {
1411 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1457 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1412 1458
1413 // Case 1: try to resolve in legacy scope and expand macro_rules 1459 // Case 1: try to resolve in legacy scope and expand macro_rules
1414 if let Some(macro_call_id) = 1460 if let Ok(Ok(macro_call_id)) = macro_call_as_call_id(
1415 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { 1461 &ast_id,
1462 self.def_collector.db,
1463 self.def_collector.def_map.krate,
1464 |path| {
1416 path.as_ident().and_then(|name| { 1465 path.as_ident().and_then(|name| {
1417 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) 1466 self.def_collector.def_map.with_ancestor_maps(
1467 self.def_collector.db,
1468 self.module_id,
1469 &mut |map, module| map[module].scope.get_legacy_macro(&name),
1470 )
1418 }) 1471 })
1419 }) 1472 },
1420 { 1473 &mut |_err| (),
1474 ) {
1421 self.def_collector.unexpanded_macros.push(MacroDirective { 1475 self.def_collector.unexpanded_macros.push(MacroDirective {
1422 module_id: self.module_id, 1476 module_id: self.module_id,
1423 ast_id, 1477 ast_id,
@@ -1470,11 +1524,10 @@ impl ModCollector<'_, '_> {
1470mod tests { 1524mod tests {
1471 use crate::{db::DefDatabase, test_db::TestDB}; 1525 use crate::{db::DefDatabase, test_db::TestDB};
1472 use base_db::{fixture::WithFixture, SourceDatabase}; 1526 use base_db::{fixture::WithFixture, SourceDatabase};
1473 use la_arena::Arena;
1474 1527
1475 use super::*; 1528 use super::*;
1476 1529
1477 fn do_collect_defs(db: &dyn DefDatabase, def_map: CrateDefMap) -> CrateDefMap { 1530 fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
1478 let mut collector = DefCollector { 1531 let mut collector = DefCollector {
1479 db, 1532 db,
1480 def_map, 1533 def_map,
@@ -1489,28 +1542,17 @@ mod tests {
1489 exports_proc_macros: false, 1542 exports_proc_macros: false,
1490 from_glob_import: Default::default(), 1543 from_glob_import: Default::default(),
1491 }; 1544 };
1545 collector.seed_with_top_level();
1492 collector.collect(); 1546 collector.collect();
1493 collector.def_map 1547 collector.def_map
1494 } 1548 }
1495 1549
1496 fn do_resolve(code: &str) -> CrateDefMap { 1550 fn do_resolve(code: &str) -> DefMap {
1497 let (db, _file_id) = TestDB::with_single_file(&code); 1551 let (db, _file_id) = TestDB::with_single_file(&code);
1498 let krate = db.test_crate(); 1552 let krate = db.test_crate();
1499 1553
1500 let def_map = { 1554 let edition = db.crate_graph()[krate].edition;
1501 let edition = db.crate_graph()[krate].edition; 1555 let def_map = DefMap::empty(krate, edition);
1502 let mut modules: Arena<ModuleData> = Arena::default();
1503 let root = modules.alloc(ModuleData::default());
1504 CrateDefMap {
1505 krate,
1506 edition,
1507 extern_prelude: FxHashMap::default(),
1508 prelude: None,
1509 root,
1510 modules,
1511 diagnostics: Vec::new(),
1512 }
1513 };
1514 do_collect_defs(&db, def_map) 1556 do_collect_defs(&db, def_map)
1515 } 1557 }
1516 1558
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 88e10574e..dd1db0094 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -10,20 +10,19 @@
10//! 10//!
11//! `ReachedFixedPoint` signals about this. 11//! `ReachedFixedPoint` signals about this.
12 12
13use std::iter::successors;
14
15use base_db::Edition; 13use base_db::Edition;
14use hir_expand::name;
16use hir_expand::name::Name; 15use hir_expand::name::Name;
17use test_utils::mark; 16use test_utils::mark;
18 17
19use crate::{ 18use crate::{
20 db::DefDatabase, 19 db::DefDatabase,
21 item_scope::BUILTIN_SCOPE, 20 item_scope::BUILTIN_SCOPE,
22 nameres::{BuiltinShadowMode, CrateDefMap}, 21 nameres::{BuiltinShadowMode, DefMap},
23 path::{ModPath, PathKind}, 22 path::{ModPath, PathKind},
24 per_ns::PerNs, 23 per_ns::PerNs,
25 visibility::{RawVisibility, Visibility}, 24 visibility::{RawVisibility, Visibility},
26 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, 25 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId,
27}; 26};
28 27
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -61,8 +60,12 @@ impl ResolvePathResult {
61 } 60 }
62} 61}
63 62
64impl CrateDefMap { 63impl DefMap {
65 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 64 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
65 if name == &name!(self) {
66 mark::hit!(extern_crate_self_as);
67 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
68 }
66 self.extern_prelude 69 self.extern_prelude
67 .get(name) 70 .get(name)
68 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) 71 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
@@ -74,7 +77,7 @@ impl CrateDefMap {
74 original_module: LocalModuleId, 77 original_module: LocalModuleId,
75 visibility: &RawVisibility, 78 visibility: &RawVisibility,
76 ) -> Option<Visibility> { 79 ) -> Option<Visibility> {
77 match visibility { 80 let mut vis = match visibility {
78 RawVisibility::Module(path) => { 81 RawVisibility::Module(path) => {
79 let (result, remaining) = 82 let (result, remaining) =
80 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); 83 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
@@ -83,15 +86,28 @@ impl CrateDefMap {
83 } 86 }
84 let types = result.take_types()?; 87 let types = result.take_types()?;
85 match types { 88 match types {
86 ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), 89 ModuleDefId::ModuleId(m) => Visibility::Module(m),
87 _ => { 90 _ => {
88 // error: visibility needs to refer to module 91 // error: visibility needs to refer to module
89 None 92 return None;
90 } 93 }
91 } 94 }
92 } 95 }
93 RawVisibility::Public => Some(Visibility::Public), 96 RawVisibility::Public => Visibility::Public,
97 };
98
99 // In block expressions, `self` normally refers to the containing non-block module, and
100 // `super` to its parent (etc.). However, visibilities must only refer to a module in the
101 // DefMap they're written in, so we restrict them when that happens.
102 if let Visibility::Module(m) = vis {
103 if self.block_id() != m.block {
104 mark::hit!(adjust_vis_in_block_def_map);
105 vis = Visibility::Module(self.module_id(self.root()));
106 log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
107 }
94 } 108 }
109
110 Some(vis)
95 } 111 }
96 112
97 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 113 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
@@ -100,30 +116,69 @@ impl CrateDefMap {
100 &self, 116 &self,
101 db: &dyn DefDatabase, 117 db: &dyn DefDatabase,
102 mode: ResolveMode, 118 mode: ResolveMode,
119 mut original_module: LocalModuleId,
120 path: &ModPath,
121 shadow: BuiltinShadowMode,
122 ) -> ResolvePathResult {
123 let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
124
125 let mut arc;
126 let mut current_map = self;
127 loop {
128 let new = current_map.resolve_path_fp_with_macro_single(
129 db,
130 mode,
131 original_module,
132 path,
133 shadow,
134 );
135
136 // Merge `new` into `result`.
137 result.resolved_def = result.resolved_def.or(new.resolved_def);
138 if result.reached_fixedpoint == ReachedFixedPoint::No {
139 result.reached_fixedpoint = new.reached_fixedpoint;
140 }
141 // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates?
142 result.krate = result.krate.or(new.krate);
143 result.segment_index = match (result.segment_index, new.segment_index) {
144 (Some(idx), None) => Some(idx),
145 (Some(old), Some(new)) => Some(old.max(new)),
146 (None, new) => new,
147 };
148
149 match &current_map.block {
150 Some(block) => {
151 original_module = block.parent.local_id;
152 arc = block.parent.def_map(db);
153 current_map = &*arc;
154 }
155 None => return result,
156 }
157 }
158 }
159
160 pub(super) fn resolve_path_fp_with_macro_single(
161 &self,
162 db: &dyn DefDatabase,
163 mode: ResolveMode,
103 original_module: LocalModuleId, 164 original_module: LocalModuleId,
104 path: &ModPath, 165 path: &ModPath,
105 shadow: BuiltinShadowMode, 166 shadow: BuiltinShadowMode,
106 ) -> ResolvePathResult { 167 ) -> ResolvePathResult {
107 let mut segments = path.segments.iter().enumerate(); 168 let mut segments = path.segments().iter().enumerate();
108 let mut curr_per_ns: PerNs = match path.kind { 169 let mut curr_per_ns: PerNs = match path.kind {
109 PathKind::DollarCrate(krate) => { 170 PathKind::DollarCrate(krate) => {
110 if krate == self.krate { 171 if krate == self.krate {
111 mark::hit!(macro_dollar_crate_self); 172 mark::hit!(macro_dollar_crate_self);
112 PerNs::types( 173 PerNs::types(self.crate_root(db).into(), Visibility::Public)
113 ModuleId { krate: self.krate, local_id: self.root }.into(),
114 Visibility::Public,
115 )
116 } else { 174 } else {
117 let def_map = db.crate_def_map(krate); 175 let def_map = db.crate_def_map(krate);
118 let module = ModuleId { krate, local_id: def_map.root }; 176 let module = def_map.module_id(def_map.root);
119 mark::hit!(macro_dollar_crate_other); 177 mark::hit!(macro_dollar_crate_other);
120 PerNs::types(module.into(), Visibility::Public) 178 PerNs::types(module.into(), Visibility::Public)
121 } 179 }
122 } 180 }
123 PathKind::Crate => PerNs::types( 181 PathKind::Crate => PerNs::types(self.crate_root(db).into(), Visibility::Public),
124 ModuleId { krate: self.krate, local_id: self.root }.into(),
125 Visibility::Public,
126 ),
127 // plain import or absolute path in 2015: crate-relative with 182 // plain import or absolute path in 2015: crate-relative with
128 // fallback to extern prelude (with the simplification in 183 // fallback to extern prelude (with the simplification in
129 // rust-lang/rust#57745) 184 // rust-lang/rust#57745)
@@ -151,23 +206,49 @@ impl CrateDefMap {
151 // BuiltinShadowMode wasn't Module, then we need to try 206 // BuiltinShadowMode wasn't Module, then we need to try
152 // resolving it as a builtin. 207 // resolving it as a builtin.
153 let prefer_module = 208 let prefer_module =
154 if path.segments.len() == 1 { shadow } else { BuiltinShadowMode::Module }; 209 if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module };
155 210
156 log::debug!("resolving {:?} in module", segment); 211 log::debug!("resolving {:?} in module", segment);
157 self.resolve_name_in_module(db, original_module, &segment, prefer_module) 212 self.resolve_name_in_module(db, original_module, &segment, prefer_module)
158 } 213 }
159 PathKind::Super(lvl) => { 214 PathKind::Super(lvl) => {
160 let m = successors(Some(original_module), |m| self.modules[*m].parent) 215 let mut module = original_module;
161 .nth(lvl as usize); 216 for i in 0..lvl {
162 if let Some(local_id) = m { 217 match self.modules[module].parent {
163 PerNs::types( 218 Some(it) => module = it,
164 ModuleId { krate: self.krate, local_id }.into(), 219 None => match &self.block {
165 Visibility::Public, 220 Some(block) => {
166 ) 221 // Look up remaining path in parent `DefMap`
167 } else { 222 let new_path = ModPath::from_segments(
168 log::debug!("super path in root module"); 223 PathKind::Super(lvl - i),
169 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 224 path.segments().to_vec(),
225 );
226 log::debug!("`super` path: {} -> {} in parent map", path, new_path);
227 return block.parent.def_map(db).resolve_path_fp_with_macro(
228 db,
229 mode,
230 block.parent.local_id,
231 &new_path,
232 shadow,
233 );
234 }
235 None => {
236 log::debug!("super path in root module");
237 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
238 }
239 },
240 }
170 } 241 }
242
243 // Resolve `self` to the containing crate-rooted module if we're a block
244 self.with_ancestor_maps(db, module, &mut |def_map, module| {
245 if def_map.block.is_some() {
246 None // keep ascending
247 } else {
248 Some(PerNs::types(def_map.module_id(module).into(), Visibility::Public))
249 }
250 })
251 .expect("block DefMap not rooted in crate DefMap")
171 } 252 }
172 PathKind::Abs => { 253 PathKind::Abs => {
173 // 2018-style absolute path -- only extern prelude 254 // 2018-style absolute path -- only extern prelude
@@ -201,12 +282,12 @@ impl CrateDefMap {
201 curr_per_ns = match curr { 282 curr_per_ns = match curr {
202 ModuleDefId::ModuleId(module) => { 283 ModuleDefId::ModuleId(module) => {
203 if module.krate != self.krate { 284 if module.krate != self.krate {
204 let path = ModPath { 285 let path = ModPath::from_segments(
205 segments: path.segments[i..].to_vec(), 286 PathKind::Super(0),
206 kind: PathKind::Super(0), 287 path.segments()[i..].iter().cloned(),
207 }; 288 );
208 log::debug!("resolving {:?} in other crate", path); 289 log::debug!("resolving {:?} in other crate", path);
209 let defp_map = db.crate_def_map(module.krate); 290 let defp_map = module.def_map(db);
210 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); 291 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
211 return ResolvePathResult::with( 292 return ResolvePathResult::with(
212 def, 293 def,
@@ -216,8 +297,16 @@ impl CrateDefMap {
216 ); 297 );
217 } 298 }
218 299
300 let def_map;
301 let module_data = if module.block == self.block_id() {
302 &self[module.local_id]
303 } else {
304 def_map = module.def_map(db);
305 &def_map[module.local_id]
306 };
307
219 // Since it is a qualified path here, it should not contains legacy macros 308 // Since it is a qualified path here, it should not contains legacy macros
220 self[module.local_id].scope.get(&segment) 309 module_data.scope.get(&segment)
221 } 310 }
222 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 311 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
223 // enum variant 312 // enum variant
@@ -319,7 +408,7 @@ impl CrateDefMap {
319 self 408 self
320 } else { 409 } else {
321 // Extend lifetime 410 // Extend lifetime
322 keep = db.crate_def_map(prelude.krate); 411 keep = prelude.def_map(db);
323 &keep 412 &keep
324 }; 413 };
325 def_map[prelude.local_id].scope.get(name) 414 def_map[prelude.local_id].scope.get(name)
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index c459fa66d..bd3e2701b 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -11,17 +11,24 @@ use base_db::{fixture::WithFixture, SourceDatabase};
11use expect_test::{expect, Expect}; 11use expect_test::{expect, Expect};
12use test_utils::mark; 12use test_utils::mark;
13 13
14use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 14use crate::{db::DefDatabase, test_db::TestDB};
15 15
16fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> { 16use super::DefMap;
17
18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
17 let db = TestDB::with_files(ra_fixture); 19 let db = TestDB::with_files(ra_fixture);
18 let krate = db.crate_graph().iter().next().unwrap(); 20 let krate = db.crate_graph().iter().next().unwrap();
19 db.crate_def_map(krate) 21 db.crate_def_map(krate)
20} 22}
21 23
24fn render_crate_def_map(ra_fixture: &str) -> String {
25 let db = TestDB::with_files(ra_fixture);
26 let krate = db.crate_graph().iter().next().unwrap();
27 db.crate_def_map(krate).dump(&db)
28}
29
22fn check(ra_fixture: &str, expect: Expect) { 30fn check(ra_fixture: &str, expect: Expect) {
23 let def_map = compute_crate_def_map(ra_fixture); 31 let actual = render_crate_def_map(ra_fixture);
24 let actual = def_map.dump();
25 expect.assert_eq(&actual); 32 expect.assert_eq(&actual);
26} 33}
27 34
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 58d69d3c6..e8e72e5ef 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -62,6 +62,22 @@ fn unresolved_extern_crate() {
62} 62}
63 63
64#[test] 64#[test]
65fn extern_crate_self_as() {
66 mark::check!(extern_crate_self_as);
67 check_diagnostics(
68 r"
69 //- /lib.rs
70 extern crate doesnotexist;
71 //^^^^^^^^^^^^^^^^^^^^^^^^^^ unresolved extern crate
72 // Should not error.
73 extern crate self as foo;
74 struct Foo;
75 use foo::Foo as Bar;
76 ",
77 );
78}
79
80#[test]
65fn dedup_unresolved_import_from_unresolved_crate() { 81fn dedup_unresolved_import_from_unresolved_crate() {
66 check_diagnostics( 82 check_diagnostics(
67 r" 83 r"
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index e5e9e8ca1..36ed5e8ce 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -391,11 +391,21 @@ foo!(ok_shadow);
391mod m4; 391mod m4;
392bar!(OkMacroUse); 392bar!(OkMacroUse);
393 393
394mod m5;
395baz!(OkMacroUseInner);
396
394//- /m3/m4.rs 397//- /m3/m4.rs
395foo!(ok_shadow_deep); 398foo!(ok_shadow_deep);
396macro_rules! bar { 399macro_rules! bar {
397 ($x:ident) => { struct $x; } 400 ($x:ident) => { struct $x; }
398} 401}
402//- /m3/m5.rs
403#![macro_use]
404macro_rules! baz {
405 ($x:ident) => { struct $x; }
406}
407
408
399"#, 409"#,
400 expect![[r#" 410 expect![[r#"
401 crate 411 crate
@@ -423,11 +433,15 @@ macro_rules! bar {
423 crate::m3 433 crate::m3
424 OkAfterInside: t v 434 OkAfterInside: t v
425 OkMacroUse: t v 435 OkMacroUse: t v
436 OkMacroUseInner: t v
426 m4: t 437 m4: t
438 m5: t
427 ok_shadow: v 439 ok_shadow: v
428 440
429 crate::m3::m4 441 crate::m3::m4
430 ok_shadow_deep: v 442 ok_shadow_deep: v
443
444 crate::m3::m5
431 "#]], 445 "#]],
432 ); 446 );
433} 447}