diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/child_by_source.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 15 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 37 | ||||
-rw-r--r-- | crates/hir_def/src/import_map.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 13 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 31 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 75 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 29 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 67 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 62 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/block.rs | 26 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 16 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 8 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/visibility.rs | 2 |
19 files changed, 244 insertions, 156 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index c72649c41..6513daec8 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -196,7 +196,7 @@ impl Attrs { | |||
196 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | 196 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { |
197 | let raw_attrs = match def { | 197 | let raw_attrs = match def { |
198 | AttrDefId::ModuleId(module) => { | 198 | AttrDefId::ModuleId(module) => { |
199 | let def_map = db.crate_def_map(module.krate); | 199 | let def_map = module.def_map(db); |
200 | let mod_data = &def_map[module.local_id]; | 200 | let mod_data = &def_map[module.local_id]; |
201 | match mod_data.declaration_source(db) { | 201 | match mod_data.declaration_source(db) { |
202 | Some(it) => { | 202 | Some(it) => { |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 2c2c999dd..d0c84ab0b 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -86,7 +86,7 @@ impl Expander { | |||
86 | module: ModuleId, | 86 | module: ModuleId, |
87 | ) -> Expander { | 87 | ) -> Expander { |
88 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); | 88 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); |
89 | let crate_def_map = db.crate_def_map(module.krate); | 89 | let crate_def_map = module.def_map(db); |
90 | let ast_id_map = db.ast_id_map(current_file_id); | 90 | let ast_id_map = db.ast_id_map(current_file_id); |
91 | Expander { | 91 | Expander { |
92 | cfg_expander, | 92 | cfg_expander, |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index dcb00a1d9..65d85c86a 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -74,7 +74,7 @@ impl ChildBySource for ImplId { | |||
74 | 74 | ||
75 | impl ChildBySource for ModuleId { | 75 | impl ChildBySource for ModuleId { |
76 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 76 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { |
77 | let crate_def_map = db.crate_def_map(self.krate); | 77 | let crate_def_map = self.def_map(db); |
78 | let module_data = &crate_def_map[self.local_id]; | 78 | let module_data = &crate_def_map[self.local_id]; |
79 | module_data.scope.child_by_source(db) | 79 | module_data.scope.child_by_source(db) |
80 | } | 80 | } |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index a87c80b8a..aef7e1f6c 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -2,9 +2,9 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use hir_expand::{db::AstDatabase, AstId, HirFileId}; | 5 | use hir_expand::{db::AstDatabase, HirFileId}; |
6 | use la_arena::ArenaMap; | 6 | use la_arena::ArenaMap; |
7 | use syntax::{ast, SmolStr}; | 7 | use syntax::SmolStr; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
@@ -16,9 +16,10 @@ use crate::{ | |||
16 | item_tree::ItemTree, | 16 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::DefMap, | 18 | nameres::DefMap, |
19 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 19 | AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, |
20 | GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, | 20 | FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, |
21 | StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, | 21 | StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, |
22 | UnionLoc, VariantId, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | #[salsa::query_group(InternDatabaseStorage)] | 25 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -41,6 +42,8 @@ pub trait InternDatabase: SourceDatabase { | |||
41 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; | 42 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; |
42 | #[salsa::interned] | 43 | #[salsa::interned] |
43 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; | 44 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; |
45 | #[salsa::interned] | ||
46 | fn intern_block(&self, loc: BlockLoc) -> BlockId; | ||
44 | } | 47 | } |
45 | 48 | ||
46 | #[salsa::query_group(DefDatabaseStorage)] | 49 | #[salsa::query_group(DefDatabaseStorage)] |
@@ -56,7 +59,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; | 59 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; |
57 | 60 | ||
58 | #[salsa::invoke(DefMap::block_def_map_query)] | 61 | #[salsa::invoke(DefMap::block_def_map_query)] |
59 | fn block_def_map(&self, krate: CrateId, block: AstId<ast::BlockExpr>) -> Arc<DefMap>; | 62 | fn block_def_map(&self, block: BlockId) -> Arc<DefMap>; |
60 | 63 | ||
61 | #[salsa::invoke(StructData::struct_data_query)] | 64 | #[salsa::invoke(StructData::struct_data_query)] |
62 | fn struct_data(&self, id: StructId) -> Arc<StructData>; | 65 | fn struct_data(&self, id: StructId) -> Arc<StructData>; |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index db2d125ae..94a1d567d 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -53,12 +53,8 @@ fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option< | |||
53 | Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) | 53 | Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) |
54 | } else if let Some(parent_id) = def_map[from.local_id].parent { | 54 | } else if let Some(parent_id) = def_map[from.local_id].parent { |
55 | // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) | 55 | // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) |
56 | if item | 56 | let parent_id = def_map.module_id(parent_id); |
57 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 57 | if item == ItemInNs::Types(ModuleDefId::ModuleId(parent_id)) { |
58 | krate: from.krate, | ||
59 | local_id: parent_id, | ||
60 | })) | ||
61 | { | ||
62 | Some(ModPath::from_segments(PathKind::Super(1), Vec::new())) | 58 | Some(ModPath::from_segments(PathKind::Super(1), Vec::new())) |
63 | } else { | 59 | } else { |
64 | None | 60 | None |
@@ -110,7 +106,7 @@ fn find_path_inner( | |||
110 | // Base cases: | 106 | // Base cases: |
111 | 107 | ||
112 | // - if the item is already in scope, return the name under which it is | 108 | // - if the item is already in scope, return the name under which it is |
113 | let def_map = db.crate_def_map(from.krate); | 109 | let def_map = from.def_map(db); |
114 | let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope; | 110 | let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope; |
115 | let scope_name = | 111 | let scope_name = |
116 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; | 112 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; |
@@ -120,12 +116,8 @@ fn find_path_inner( | |||
120 | } | 116 | } |
121 | 117 | ||
122 | // - if the item is the crate root, return `crate` | 118 | // - if the item is the crate root, return `crate` |
123 | if item | 119 | let root = def_map.module_id(def_map.root()); |
124 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 120 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) { |
125 | krate: from.krate, | ||
126 | local_id: def_map.root(), | ||
127 | })) | ||
128 | { | ||
129 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 121 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
130 | } | 122 | } |
131 | 123 | ||
@@ -145,7 +137,7 @@ fn find_path_inner( | |||
145 | 137 | ||
146 | // - if the item is in the prelude, return the name from there | 138 | // - if the item is in the prelude, return the name from there |
147 | if let Some(prelude_module) = def_map.prelude() { | 139 | if let Some(prelude_module) = def_map.prelude() { |
148 | let prelude_def_map = db.crate_def_map(prelude_module.krate); | 140 | let prelude_def_map = prelude_module.def_map(db); |
149 | let prelude_scope: &crate::item_scope::ItemScope = | 141 | let prelude_scope: &crate::item_scope::ItemScope = |
150 | &prelude_def_map[prelude_module.local_id].scope; | 142 | &prelude_def_map[prelude_module.local_id].scope; |
151 | if let Some((name, vis)) = prelude_scope.name_of(item) { | 143 | if let Some((name, vis)) = prelude_scope.name_of(item) { |
@@ -175,7 +167,7 @@ fn find_path_inner( | |||
175 | 167 | ||
176 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 168 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
177 | 169 | ||
178 | let crate_root = ModuleId { local_id: def_map.root(), krate: from.krate }; | 170 | let crate_root = def_map.module_id(def_map.root()); |
179 | let crate_attrs = db.attrs(crate_root.into()); | 171 | let crate_attrs = db.attrs(crate_root.into()); |
180 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 172 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
181 | let mut best_path = None; | 173 | let mut best_path = None; |
@@ -283,19 +275,16 @@ fn find_local_import_locations( | |||
283 | // above `from` with any visibility. That means we do not need to descend into private siblings | 275 | // above `from` with any visibility. That means we do not need to descend into private siblings |
284 | // of `from` (and similar). | 276 | // of `from` (and similar). |
285 | 277 | ||
286 | let def_map = db.crate_def_map(from.krate); | 278 | let def_map = from.def_map(db); |
287 | 279 | ||
288 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all | 280 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all |
289 | // of its (recursive) parent modules. | 281 | // of its (recursive) parent modules. |
290 | let data = &def_map[from.local_id]; | 282 | let data = &def_map[from.local_id]; |
291 | let mut worklist = data | 283 | let mut worklist = |
292 | .children | 284 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); |
293 | .values() | ||
294 | .map(|child| ModuleId { krate: from.krate, local_id: *child }) | ||
295 | .collect::<Vec<_>>(); | ||
296 | let mut parent = data.parent; | 285 | let mut parent = data.parent; |
297 | while let Some(p) = parent { | 286 | while let Some(p) = parent { |
298 | worklist.push(ModuleId { krate: from.krate, local_id: p }); | 287 | worklist.push(def_map.module_id(p)); |
299 | parent = def_map[p].parent; | 288 | parent = def_map[p].parent; |
300 | } | 289 | } |
301 | 290 | ||
@@ -312,7 +301,7 @@ fn find_local_import_locations( | |||
312 | &def_map[module.local_id] | 301 | &def_map[module.local_id] |
313 | } else { | 302 | } else { |
314 | // The crate might reexport a module defined in another crate. | 303 | // The crate might reexport a module defined in another crate. |
315 | ext_def_map = db.crate_def_map(module.krate); | 304 | ext_def_map = module.def_map(db); |
316 | &ext_def_map[module.local_id] | 305 | &ext_def_map[module.local_id] |
317 | }; | 306 | }; |
318 | 307 | ||
@@ -375,7 +364,7 @@ mod tests { | |||
375 | parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap(); | 364 | parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap(); |
376 | let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap(); | 365 | let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap(); |
377 | 366 | ||
378 | let crate_def_map = db.crate_def_map(module.krate); | 367 | let crate_def_map = module.def_map(&db); |
379 | let resolved = crate_def_map | 368 | let resolved = crate_def_map |
380 | .resolve_path( | 369 | .resolve_path( |
381 | &db, | 370 | &db, |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 0251d016b..0a3dc7956 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -75,7 +75,7 @@ impl ImportMap { | |||
75 | 75 | ||
76 | // We look only into modules that are public(ly reexported), starting with the crate root. | 76 | // We look only into modules that are public(ly reexported), starting with the crate root. |
77 | let empty = ImportPath { segments: vec![] }; | 77 | let empty = ImportPath { segments: vec![] }; |
78 | let root = ModuleId { krate, local_id: def_map.root() }; | 78 | let root = def_map.module_id(def_map.root()); |
79 | let mut worklist = vec![(root, empty)]; | 79 | let mut worklist = vec![(root, empty)]; |
80 | while let Some((module, mod_path)) = worklist.pop() { | 80 | while let Some((module, mod_path)) = worklist.pop() { |
81 | let ext_def_map; | 81 | let ext_def_map; |
@@ -83,7 +83,7 @@ impl ImportMap { | |||
83 | &def_map[module.local_id] | 83 | &def_map[module.local_id] |
84 | } else { | 84 | } else { |
85 | // The crate might reexport a module defined in another crate. | 85 | // The crate might reexport a module defined in another crate. |
86 | ext_def_map = db.crate_def_map(module.krate); | 86 | ext_def_map = module.def_map(db); |
87 | &ext_def_map[module.local_id] | 87 | &ext_def_map[module.local_id] |
88 | }; | 88 | }; |
89 | 89 | ||
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index b8d7608e7..1e5c94660 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -66,7 +66,7 @@ impl GenericParamsId { | |||
66 | } | 66 | } |
67 | 67 | ||
68 | /// The item tree of a source file. | 68 | /// The item tree of a source file. |
69 | #[derive(Debug, Eq, PartialEq)] | 69 | #[derive(Debug, Default, Eq, PartialEq)] |
70 | pub struct ItemTree { | 70 | pub struct ItemTree { |
71 | _c: Count<Self>, | 71 | _c: Count<Self>, |
72 | 72 | ||
@@ -82,7 +82,7 @@ impl ItemTree { | |||
82 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { | 82 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { |
83 | node | 83 | node |
84 | } else { | 84 | } else { |
85 | return Arc::new(Self::empty()); | 85 | return Default::default(); |
86 | }; | 86 | }; |
87 | 87 | ||
88 | let hygiene = Hygiene::new(db.upcast(), file_id); | 88 | let hygiene = Hygiene::new(db.upcast(), file_id); |
@@ -118,15 +118,6 @@ impl ItemTree { | |||
118 | Arc::new(item_tree) | 118 | Arc::new(item_tree) |
119 | } | 119 | } |
120 | 120 | ||
121 | fn empty() -> Self { | ||
122 | Self { | ||
123 | _c: Count::new(), | ||
124 | top_level: Default::default(), | ||
125 | attrs: Default::default(), | ||
126 | data: Default::default(), | ||
127 | } | ||
128 | } | ||
129 | |||
130 | fn shrink_to_fit(&mut self) { | 121 | fn shrink_to_fit(&mut self) { |
131 | if let Some(data) = &mut self.data { | 122 | if let Some(data) = &mut self.data { |
132 | let ItemTreeData { | 123 | let ItemTreeData { |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index ce470fc3b..8a71376b9 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -43,7 +43,7 @@ pub(super) struct Ctx { | |||
43 | impl Ctx { | 43 | impl Ctx { |
44 | pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { | 44 | pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { |
45 | Self { | 45 | Self { |
46 | tree: ItemTree::empty(), | 46 | tree: ItemTree::default(), |
47 | hygiene, | 47 | hygiene, |
48 | file, | 48 | file, |
49 | source_ast_id_map: db.ast_id_map(file), | 49 | source_ast_id_map: db.ast_id_map(file), |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 08ed920c6..42b50b5b7 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -50,7 +50,10 @@ pub mod import_map; | |||
50 | #[cfg(test)] | 50 | #[cfg(test)] |
51 | mod test_db; | 51 | mod test_db; |
52 | 52 | ||
53 | use std::hash::{Hash, Hasher}; | 53 | use std::{ |
54 | hash::{Hash, Hasher}, | ||
55 | sync::Arc, | ||
56 | }; | ||
54 | 57 | ||
55 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
56 | use hir_expand::{ | 59 | use hir_expand::{ |
@@ -58,6 +61,7 @@ use hir_expand::{ | |||
58 | MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 61 | MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
59 | }; | 62 | }; |
60 | use la_arena::Idx; | 63 | use la_arena::Idx; |
64 | use nameres::DefMap; | ||
61 | use syntax::ast; | 65 | use syntax::ast; |
62 | 66 | ||
63 | use crate::builtin_type::BuiltinType; | 67 | use crate::builtin_type::BuiltinType; |
@@ -69,10 +73,24 @@ use stdx::impl_from; | |||
69 | 73 | ||
70 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 74 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
71 | pub struct ModuleId { | 75 | pub struct ModuleId { |
72 | pub krate: CrateId, | 76 | krate: CrateId, |
77 | block: Option<BlockId>, | ||
73 | pub local_id: LocalModuleId, | 78 | pub local_id: LocalModuleId, |
74 | } | 79 | } |
75 | 80 | ||
81 | impl ModuleId { | ||
82 | pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> { | ||
83 | match self.block { | ||
84 | Some(block) => db.block_def_map(block), | ||
85 | None => db.crate_def_map(self.krate), | ||
86 | } | ||
87 | } | ||
88 | |||
89 | pub fn krate(&self) -> CrateId { | ||
90 | self.krate | ||
91 | } | ||
92 | } | ||
93 | |||
76 | /// An ID of a module, **local** to a specific crate | 94 | /// An ID of a module, **local** to a specific crate |
77 | pub type LocalModuleId = Idx<nameres::ModuleData>; | 95 | pub type LocalModuleId = Idx<nameres::ModuleData>; |
78 | 96 | ||
@@ -216,6 +234,15 @@ pub struct ImplId(salsa::InternId); | |||
216 | type ImplLoc = ItemLoc<Impl>; | 234 | type ImplLoc = ItemLoc<Impl>; |
217 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | 235 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); |
218 | 236 | ||
237 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
238 | pub struct BlockId(salsa::InternId); | ||
239 | #[derive(Debug, Hash, PartialEq, Eq, Clone)] | ||
240 | pub struct BlockLoc { | ||
241 | ast_id: AstId<ast::BlockExpr>, | ||
242 | module: ModuleId, | ||
243 | } | ||
244 | impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); | ||
245 | |||
219 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 246 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
220 | pub struct TypeParamId { | 247 | pub struct TypeParamId { |
221 | pub parent: GenericDefId, | 248 | pub parent: GenericDefId, |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index bd3ea9b8b..199771e9a 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -62,7 +62,7 @@ use la_arena::Arena; | |||
62 | use profile::Count; | 62 | use profile::Count; |
63 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
64 | use stdx::format_to; | 64 | use stdx::format_to; |
65 | use syntax::{ast, AstNode}; | 65 | use syntax::ast; |
66 | 66 | ||
67 | use crate::{ | 67 | use crate::{ |
68 | db::DefDatabase, | 68 | db::DefDatabase, |
@@ -70,14 +70,14 @@ use crate::{ | |||
70 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, | 70 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, |
71 | path::ModPath, | 71 | path::ModPath, |
72 | per_ns::PerNs, | 72 | per_ns::PerNs, |
73 | AstId, LocalModuleId, ModuleDefId, ModuleId, | 73 | AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | /// Contains all top-level defs from a macro-expanded crate | 76 | /// Contains all top-level defs from a macro-expanded crate |
77 | #[derive(Debug, PartialEq, Eq)] | 77 | #[derive(Debug, PartialEq, Eq)] |
78 | pub struct DefMap { | 78 | pub struct DefMap { |
79 | _c: Count<Self>, | 79 | _c: Count<Self>, |
80 | parent: Option<Arc<DefMap>>, | 80 | block: Option<BlockInfo>, |
81 | root: LocalModuleId, | 81 | root: LocalModuleId, |
82 | modules: Arena<ModuleData>, | 82 | modules: Arena<ModuleData>, |
83 | krate: CrateId, | 83 | krate: CrateId, |
@@ -91,6 +91,13 @@ pub struct DefMap { | |||
91 | diagnostics: Vec<DefDiagnostic>, | 91 | diagnostics: Vec<DefDiagnostic>, |
92 | } | 92 | } |
93 | 93 | ||
94 | #[derive(Debug, PartialEq, Eq)] | ||
95 | struct BlockInfo { | ||
96 | block: BlockId, | ||
97 | parent: Arc<DefMap>, | ||
98 | parent_module: LocalModuleId, | ||
99 | } | ||
100 | |||
94 | impl std::ops::Index<LocalModuleId> for DefMap { | 101 | impl std::ops::Index<LocalModuleId> for DefMap { |
95 | type Output = ModuleData; | 102 | type Output = ModuleData; |
96 | fn index(&self, id: LocalModuleId) -> &ModuleData { | 103 | fn index(&self, id: LocalModuleId) -> &ModuleData { |
@@ -190,15 +197,12 @@ impl DefMap { | |||
190 | Arc::new(def_map) | 197 | Arc::new(def_map) |
191 | } | 198 | } |
192 | 199 | ||
193 | pub(crate) fn block_def_map_query( | 200 | pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> { |
194 | db: &dyn DefDatabase, | 201 | let block: BlockLoc = db.lookup_intern_block(block_id); |
195 | krate: CrateId, | 202 | let item_tree = db.item_tree(block.ast_id.file_id); |
196 | block: AstId<ast::BlockExpr>, | 203 | let block_items = item_tree.inner_items_of_block(block.ast_id.value); |
197 | ) -> Arc<DefMap> { | ||
198 | let item_tree = db.item_tree(block.file_id); | ||
199 | let block_items = item_tree.inner_items_of_block(block.value); | ||
200 | 204 | ||
201 | let parent = parent_def_map(db, krate, block); | 205 | let parent = block.module.def_map(db); |
202 | 206 | ||
203 | if block_items.is_empty() { | 207 | if block_items.is_empty() { |
204 | // If there are no inner items, nothing new is brought into scope, so we can just return | 208 | // If there are no inner items, nothing new is brought into scope, so we can just return |
@@ -206,10 +210,13 @@ impl DefMap { | |||
206 | return parent; | 210 | return parent; |
207 | } | 211 | } |
208 | 212 | ||
209 | let mut def_map = DefMap::empty(krate, parent.edition); | 213 | let block_info = |
210 | def_map.parent = Some(parent); | 214 | BlockInfo { block: block_id, parent, parent_module: block.module.local_id }; |
215 | |||
216 | let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition); | ||
217 | def_map.block = Some(block_info); | ||
211 | 218 | ||
212 | let def_map = collector::collect_defs(db, def_map, Some(block.value)); | 219 | let def_map = collector::collect_defs(db, def_map, Some(block.ast_id.value)); |
213 | Arc::new(def_map) | 220 | Arc::new(def_map) |
214 | } | 221 | } |
215 | 222 | ||
@@ -218,7 +225,7 @@ impl DefMap { | |||
218 | let root = modules.alloc(ModuleData::default()); | 225 | let root = modules.alloc(ModuleData::default()); |
219 | DefMap { | 226 | DefMap { |
220 | _c: Count::new(), | 227 | _c: Count::new(), |
221 | parent: None, | 228 | block: None, |
222 | krate, | 229 | krate, |
223 | edition, | 230 | edition, |
224 | extern_prelude: FxHashMap::default(), | 231 | extern_prelude: FxHashMap::default(), |
@@ -265,6 +272,11 @@ impl DefMap { | |||
265 | self.extern_prelude.iter() | 272 | self.extern_prelude.iter() |
266 | } | 273 | } |
267 | 274 | ||
275 | pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId { | ||
276 | let block = self.block.as_ref().map(|b| b.block); | ||
277 | ModuleId { krate: self.krate, local_id, block } | ||
278 | } | ||
279 | |||
268 | pub(crate) fn resolve_path( | 280 | pub(crate) fn resolve_path( |
269 | &self, | 281 | &self, |
270 | db: &dyn DefDatabase, | 282 | db: &dyn DefDatabase, |
@@ -282,9 +294,9 @@ impl DefMap { | |||
282 | pub fn dump(&self) -> String { | 294 | pub fn dump(&self) -> String { |
283 | let mut buf = String::new(); | 295 | let mut buf = String::new(); |
284 | let mut current_map = self; | 296 | let mut current_map = self; |
285 | while let Some(parent) = ¤t_map.parent { | 297 | while let Some(block) = ¤t_map.block { |
286 | go(&mut buf, current_map, "block scope", current_map.root); | 298 | go(&mut buf, current_map, "block scope", current_map.root); |
287 | current_map = &**parent; | 299 | current_map = &*block.parent; |
288 | } | 300 | } |
289 | go(&mut buf, current_map, "crate", current_map.root); | 301 | go(&mut buf, current_map, "crate", current_map.root); |
290 | return buf; | 302 | return buf; |
@@ -338,35 +350,6 @@ impl ModuleData { | |||
338 | } | 350 | } |
339 | } | 351 | } |
340 | 352 | ||
341 | fn parent_def_map( | ||
342 | db: &dyn DefDatabase, | ||
343 | krate: CrateId, | ||
344 | block: AstId<ast::BlockExpr>, | ||
345 | ) -> Arc<DefMap> { | ||
346 | // FIXME: store this info in the item tree instead of reparsing here | ||
347 | let ast_id_map = db.ast_id_map(block.file_id); | ||
348 | let block_ptr = ast_id_map.get(block.value); | ||
349 | let root = match db.parse_or_expand(block.file_id) { | ||
350 | Some(it) => it, | ||
351 | None => { | ||
352 | return Arc::new(DefMap::empty(krate, Edition::Edition2018)); | ||
353 | } | ||
354 | }; | ||
355 | let ast = block_ptr.to_node(&root); | ||
356 | |||
357 | for ancestor in ast.syntax().ancestors().skip(1) { | ||
358 | if let Some(block_expr) = ast::BlockExpr::cast(ancestor) { | ||
359 | let ancestor_id = ast_id_map.ast_id(&block_expr); | ||
360 | let ast_id = InFile::new(block.file_id, ancestor_id); | ||
361 | let parent_map = db.block_def_map(krate, ast_id); | ||
362 | return parent_map; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | // No enclosing block scope, so the parent is the crate-level DefMap. | ||
367 | db.crate_def_map(krate) | ||
368 | } | ||
369 | |||
370 | #[derive(Debug, Clone, PartialEq, Eq)] | 353 | #[derive(Debug, Clone, PartialEq, Eq)] |
371 | pub enum ModuleSource { | 354 | pub enum ModuleSource { |
372 | SourceFile(ast::SourceFile), | 355 | SourceFile(ast::SourceFile), |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index cd68efbe6..393170b32 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -37,8 +37,8 @@ use crate::{ | |||
37 | per_ns::PerNs, | 37 | per_ns::PerNs, |
38 | visibility::{RawVisibility, Visibility}, | 38 | visibility::{RawVisibility, Visibility}, |
39 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, | 39 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, |
40 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, | 40 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, StaticLoc, StructLoc, TraitLoc, |
41 | TraitLoc, TypeAliasLoc, UnionLoc, | 41 | TypeAliasLoc, UnionLoc, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | const GLOB_RECURSION_LIMIT: usize = 100; | 44 | const GLOB_RECURSION_LIMIT: usize = 100; |
@@ -56,10 +56,9 @@ pub(super) fn collect_defs( | |||
56 | for dep in &crate_graph[def_map.krate].dependencies { | 56 | for dep in &crate_graph[def_map.krate].dependencies { |
57 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); | 57 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); |
58 | let dep_def_map = db.crate_def_map(dep.crate_id); | 58 | let dep_def_map = db.crate_def_map(dep.crate_id); |
59 | def_map.extern_prelude.insert( | 59 | def_map |
60 | dep.as_name(), | 60 | .extern_prelude |
61 | ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(), | 61 | .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); |
62 | ); | ||
63 | 62 | ||
64 | // look for the prelude | 63 | // look for the prelude |
65 | // If the dependency defines a prelude, we overwrite an already defined | 64 | // If the dependency defines a prelude, we overwrite an already defined |
@@ -332,11 +331,9 @@ impl DefCollector<'_> { | |||
332 | // exported in type/value namespace. This function reduces the visibility of all items | 331 | // exported in type/value namespace. This function reduces the visibility of all items |
333 | // in the crate root that aren't proc macros. | 332 | // in the crate root that aren't proc macros. |
334 | let root = self.def_map.root; | 333 | let root = self.def_map.root; |
334 | let module_id = self.def_map.module_id(root); | ||
335 | let root = &mut self.def_map.modules[root]; | 335 | let root = &mut self.def_map.modules[root]; |
336 | root.scope.censor_non_proc_macros(ModuleId { | 336 | root.scope.censor_non_proc_macros(module_id); |
337 | krate: self.def_map.krate, | ||
338 | local_id: self.def_map.root, | ||
339 | }); | ||
340 | } | 337 | } |
341 | } | 338 | } |
342 | 339 | ||
@@ -578,7 +575,7 @@ impl DefCollector<'_> { | |||
578 | } else if m.krate != self.def_map.krate { | 575 | } else if m.krate != self.def_map.krate { |
579 | mark::hit!(glob_across_crates); | 576 | mark::hit!(glob_across_crates); |
580 | // glob import from other crate => we can just import everything once | 577 | // glob import from other crate => we can just import everything once |
581 | let item_map = self.db.crate_def_map(m.krate); | 578 | let item_map = m.def_map(self.db); |
582 | let scope = &item_map[m.local_id].scope; | 579 | let scope = &item_map[m.local_id].scope; |
583 | 580 | ||
584 | // Module scoped macros is included | 581 | // Module scoped macros is included |
@@ -1029,8 +1026,7 @@ impl ModCollector<'_, '_> { | |||
1029 | continue; | 1026 | continue; |
1030 | } | 1027 | } |
1031 | } | 1028 | } |
1032 | let module = | 1029 | let module = self.def_collector.def_map.module_id(self.module_id); |
1033 | ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; | ||
1034 | let container = ContainerId::ModuleId(module); | 1030 | let container = ContainerId::ModuleId(module); |
1035 | 1031 | ||
1036 | let mut def = None; | 1032 | let mut def = None; |
@@ -1097,10 +1093,7 @@ impl ModCollector<'_, '_> { | |||
1097 | } | 1093 | } |
1098 | } | 1094 | } |
1099 | ModItem::Impl(imp) => { | 1095 | ModItem::Impl(imp) => { |
1100 | let module = ModuleId { | 1096 | let module = self.def_collector.def_map.module_id(self.module_id); |
1101 | krate: self.def_collector.def_map.krate, | ||
1102 | local_id: self.module_id, | ||
1103 | }; | ||
1104 | let container = ContainerId::ModuleId(module); | 1097 | let container = ContainerId::ModuleId(module); |
1105 | let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } | 1098 | let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } |
1106 | .intern(self.def_collector.db); | 1099 | .intern(self.def_collector.db); |
@@ -1343,7 +1336,7 @@ impl ModCollector<'_, '_> { | |||
1343 | modules[res].scope.define_legacy_macro(name, mac) | 1336 | modules[res].scope.define_legacy_macro(name, mac) |
1344 | } | 1337 | } |
1345 | modules[self.module_id].children.insert(name.clone(), res); | 1338 | modules[self.module_id].children.insert(name.clone(), res); |
1346 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 1339 | let module = self.def_collector.def_map.module_id(res); |
1347 | let def: ModuleDefId = module.into(); | 1340 | let def: ModuleDefId = module.into(); |
1348 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1341 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1349 | self.def_collector.update( | 1342 | self.def_collector.update( |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index ec90f4e65..419e465ed 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -10,9 +10,8 @@ | |||
10 | //! | 10 | //! |
11 | //! `ReachedFixedPoint` signals about this. | 11 | //! `ReachedFixedPoint` signals about this. |
12 | 12 | ||
13 | use std::iter::successors; | ||
14 | |||
15 | use base_db::Edition; | 13 | use base_db::Edition; |
14 | use hir_expand::name; | ||
16 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
17 | use test_utils::mark; | 16 | use test_utils::mark; |
18 | 17 | ||
@@ -23,7 +22,7 @@ use crate::{ | |||
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)] |
@@ -63,6 +62,10 @@ impl ResolvePathResult { | |||
63 | 62 | ||
64 | impl DefMap { | 63 | impl 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)) |
@@ -126,8 +129,8 @@ impl DefMap { | |||
126 | result.krate = result.krate.or(new.krate); | 129 | result.krate = result.krate.or(new.krate); |
127 | result.segment_index = result.segment_index.min(new.segment_index); | 130 | result.segment_index = result.segment_index.min(new.segment_index); |
128 | 131 | ||
129 | match ¤t_map.parent { | 132 | match ¤t_map.block { |
130 | Some(map) => current_map = map, | 133 | Some(block) => current_map = &block.parent, |
131 | None => return result, | 134 | None => return result, |
132 | } | 135 | } |
133 | } | 136 | } |
@@ -146,21 +149,15 @@ impl DefMap { | |||
146 | PathKind::DollarCrate(krate) => { | 149 | PathKind::DollarCrate(krate) => { |
147 | if krate == self.krate { | 150 | if krate == self.krate { |
148 | mark::hit!(macro_dollar_crate_self); | 151 | mark::hit!(macro_dollar_crate_self); |
149 | PerNs::types( | 152 | PerNs::types(self.module_id(self.root).into(), Visibility::Public) |
150 | ModuleId { krate: self.krate, local_id: self.root }.into(), | ||
151 | Visibility::Public, | ||
152 | ) | ||
153 | } else { | 153 | } else { |
154 | let def_map = db.crate_def_map(krate); | 154 | let def_map = db.crate_def_map(krate); |
155 | let module = ModuleId { krate, local_id: def_map.root }; | 155 | let module = def_map.module_id(def_map.root); |
156 | mark::hit!(macro_dollar_crate_other); | 156 | mark::hit!(macro_dollar_crate_other); |
157 | PerNs::types(module.into(), Visibility::Public) | 157 | PerNs::types(module.into(), Visibility::Public) |
158 | } | 158 | } |
159 | } | 159 | } |
160 | PathKind::Crate => PerNs::types( | 160 | PathKind::Crate => PerNs::types(self.module_id(self.root).into(), Visibility::Public), |
161 | ModuleId { krate: self.krate, local_id: self.root }.into(), | ||
162 | Visibility::Public, | ||
163 | ), | ||
164 | // plain import or absolute path in 2015: crate-relative with | 161 | // plain import or absolute path in 2015: crate-relative with |
165 | // fallback to extern prelude (with the simplification in | 162 | // fallback to extern prelude (with the simplification in |
166 | // rust-lang/rust#57745) | 163 | // rust-lang/rust#57745) |
@@ -194,17 +191,35 @@ impl DefMap { | |||
194 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) | 191 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) |
195 | } | 192 | } |
196 | PathKind::Super(lvl) => { | 193 | PathKind::Super(lvl) => { |
197 | let m = successors(Some(original_module), |m| self.modules[*m].parent) | 194 | let mut module = original_module; |
198 | .nth(lvl as usize); | 195 | for i in 0..lvl { |
199 | if let Some(local_id) = m { | 196 | match self.modules[module].parent { |
200 | PerNs::types( | 197 | Some(it) => module = it, |
201 | ModuleId { krate: self.krate, local_id }.into(), | 198 | None => match &self.block { |
202 | Visibility::Public, | 199 | Some(block) => { |
203 | ) | 200 | // Look up remaining path in parent `DefMap` |
204 | } else { | 201 | let new_path = ModPath { |
205 | log::debug!("super path in root module"); | 202 | kind: PathKind::Super(lvl - i), |
206 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 203 | segments: path.segments.clone(), |
204 | }; | ||
205 | log::debug!("`super` path: {} -> {} in parent map", path, new_path); | ||
206 | return block.parent.resolve_path_fp_with_macro( | ||
207 | db, | ||
208 | mode, | ||
209 | block.parent_module, | ||
210 | &new_path, | ||
211 | shadow, | ||
212 | ); | ||
213 | } | ||
214 | None => { | ||
215 | log::debug!("super path in root module"); | ||
216 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | ||
217 | } | ||
218 | }, | ||
219 | } | ||
207 | } | 220 | } |
221 | |||
222 | PerNs::types(self.module_id(module).into(), Visibility::Public) | ||
208 | } | 223 | } |
209 | PathKind::Abs => { | 224 | PathKind::Abs => { |
210 | // 2018-style absolute path -- only extern prelude | 225 | // 2018-style absolute path -- only extern prelude |
@@ -243,7 +258,7 @@ impl DefMap { | |||
243 | kind: PathKind::Super(0), | 258 | kind: PathKind::Super(0), |
244 | }; | 259 | }; |
245 | log::debug!("resolving {:?} in other crate", path); | 260 | log::debug!("resolving {:?} in other crate", path); |
246 | let defp_map = db.crate_def_map(module.krate); | 261 | let defp_map = module.def_map(db); |
247 | let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); | 262 | let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); |
248 | return ResolvePathResult::with( | 263 | return ResolvePathResult::with( |
249 | def, | 264 | def, |
@@ -356,7 +371,7 @@ impl DefMap { | |||
356 | self | 371 | self |
357 | } else { | 372 | } else { |
358 | // Extend lifetime | 373 | // Extend lifetime |
359 | keep = db.crate_def_map(prelude.krate); | 374 | keep = prelude.def_map(db); |
360 | &keep | 375 | &keep |
361 | }; | 376 | }; |
362 | def_map[prelude.local_id].scope.get(name) | 377 | 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 73e3a4702..b36d0b59b 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -8,12 +8,12 @@ mod block; | |||
8 | 8 | ||
9 | use std::sync::Arc; | 9 | use std::sync::Arc; |
10 | 10 | ||
11 | use base_db::{fixture::WithFixture, SourceDatabase}; | 11 | use base_db::{fixture::WithFixture, FilePosition, SourceDatabase}; |
12 | use expect_test::{expect, Expect}; | 12 | use expect_test::{expect, Expect}; |
13 | use hir_expand::db::AstDatabase; | 13 | use syntax::AstNode; |
14 | use test_utils::mark; | 14 | use test_utils::mark; |
15 | 15 | ||
16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, Lookup}; |
17 | 17 | ||
18 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | 18 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { |
19 | let db = TestDB::with_files(ra_fixture); | 19 | let db = TestDB::with_files(ra_fixture); |
@@ -23,14 +23,58 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | |||
23 | 23 | ||
24 | fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { | 24 | fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { |
25 | let (db, position) = TestDB::with_position(ra_fixture); | 25 | let (db, position) = TestDB::with_position(ra_fixture); |
26 | |||
27 | // FIXME: perhaps we should make this use body lowering tests instead? | ||
28 | |||
26 | let module = db.module_for_file(position.file_id); | 29 | let module = db.module_for_file(position.file_id); |
27 | let ast_map = db.ast_id_map(position.file_id.into()); | 30 | let mut def_map = db.crate_def_map(module.krate); |
28 | let ast = db.parse(position.file_id); | 31 | while let Some(new_def_map) = descend_def_map_at_position(&db, position, def_map.clone()) { |
29 | let block: ast::BlockExpr = | 32 | def_map = new_def_map; |
30 | syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap(); | 33 | } |
31 | let block_id = ast_map.ast_id(&block); | 34 | |
35 | // FIXME: select the right module, not the root | ||
36 | |||
37 | def_map | ||
38 | } | ||
39 | |||
40 | fn descend_def_map_at_position( | ||
41 | db: &dyn DefDatabase, | ||
42 | position: FilePosition, | ||
43 | def_map: Arc<DefMap>, | ||
44 | ) -> Option<Arc<DefMap>> { | ||
45 | for (local_id, module_data) in def_map.modules() { | ||
46 | let mod_def = module_data.origin.definition_source(db); | ||
47 | let ast_map = db.ast_id_map(mod_def.file_id); | ||
48 | let item_tree = db.item_tree(mod_def.file_id); | ||
49 | let root = db.parse_or_expand(mod_def.file_id).unwrap(); | ||
50 | for item in module_data.scope.declarations() { | ||
51 | match item { | ||
52 | ModuleDefId::FunctionId(it) => { | ||
53 | // Technically blocks can be inside any type (due to arrays and const generics), | ||
54 | // and also in const/static initializers. For tests we only really care about | ||
55 | // functions though. | ||
56 | |||
57 | let ast = ast_map.get(item_tree[it.lookup(db).id.value].ast_id).to_node(&root); | ||
58 | |||
59 | if ast.syntax().text_range().contains(position.offset) { | ||
60 | // Cursor inside function, descend into its body's DefMap. | ||
61 | // Note that we don't handle block *expressions* inside function bodies. | ||
62 | let ast_map = db.ast_id_map(position.file_id.into()); | ||
63 | let ast_id = ast_map.ast_id(&ast.body().unwrap()); | ||
64 | let block = BlockLoc { | ||
65 | ast_id: InFile::new(position.file_id.into(), ast_id), | ||
66 | module: def_map.module_id(local_id), | ||
67 | }; | ||
68 | let block_id = db.intern_block(block); | ||
69 | return Some(db.block_def_map(block_id)); | ||
70 | } | ||
71 | } | ||
72 | _ => continue, | ||
73 | } | ||
74 | } | ||
75 | } | ||
32 | 76 | ||
33 | db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id)) | 77 | None |
34 | } | 78 | } |
35 | 79 | ||
36 | fn check(ra_fixture: &str, expect: Expect) { | 80 | fn check(ra_fixture: &str, expect: Expect) { |
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs index 01d6326a7..470ca593e 100644 --- a/crates/hir_def/src/nameres/tests/block.rs +++ b/crates/hir_def/src/nameres/tests/block.rs | |||
@@ -95,3 +95,29 @@ fn outer() { | |||
95 | "#]], | 95 | "#]], |
96 | ); | 96 | ); |
97 | } | 97 | } |
98 | |||
99 | #[test] | ||
100 | fn super_imports() { | ||
101 | check_at( | ||
102 | r#" | ||
103 | mod module { | ||
104 | fn f() { | ||
105 | use super::Struct; | ||
106 | $0 | ||
107 | } | ||
108 | } | ||
109 | |||
110 | struct Struct {} | ||
111 | "#, | ||
112 | expect![[r#" | ||
113 | block scope | ||
114 | Struct: t | ||
115 | crate | ||
116 | Struct: t | ||
117 | module: t | ||
118 | |||
119 | crate::module | ||
120 | f: v | ||
121 | "#]], | ||
122 | ); | ||
123 | } | ||
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] |
65 | fn 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] | ||
65 | fn dedup_unresolved_import_from_unresolved_crate() { | 81 | fn dedup_unresolved_import_from_unresolved_crate() { |
66 | check_diagnostics( | 82 | check_diagnostics( |
67 | r" | 83 | r" |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index e34cd7f2f..84ea09b53 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -304,6 +304,7 @@ pub use hir_expand::name as __name; | |||
304 | #[macro_export] | 304 | #[macro_export] |
305 | macro_rules! __known_path { | 305 | macro_rules! __known_path { |
306 | (core::iter::IntoIterator) => {}; | 306 | (core::iter::IntoIterator) => {}; |
307 | (core::iter::Iterator) => {}; | ||
307 | (core::result::Result) => {}; | 308 | (core::result::Result) => {}; |
308 | (core::option::Option) => {}; | 309 | (core::option::Option) => {}; |
309 | (core::ops::Range) => {}; | 310 | (core::ops::Range) => {}; |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index b2f577649..9021ea712 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -430,7 +430,7 @@ impl Resolver { | |||
430 | for scope in &self.scopes { | 430 | for scope in &self.scopes { |
431 | if let Scope::ModuleScope(m) = scope { | 431 | if let Scope::ModuleScope(m) = scope { |
432 | if let Some(prelude) = m.crate_def_map.prelude() { | 432 | if let Some(prelude) = m.crate_def_map.prelude() { |
433 | let prelude_def_map = db.crate_def_map(prelude.krate); | 433 | let prelude_def_map = prelude.def_map(db); |
434 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | 434 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); |
435 | } | 435 | } |
436 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); | 436 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); |
@@ -459,7 +459,7 @@ impl Resolver { | |||
459 | 459 | ||
460 | pub fn module(&self) -> Option<ModuleId> { | 460 | pub fn module(&self) -> Option<ModuleId> { |
461 | let (def_map, local_id) = self.module_scope()?; | 461 | let (def_map, local_id) = self.module_scope()?; |
462 | Some(ModuleId { krate: def_map.krate(), local_id }) | 462 | Some(def_map.module_id(local_id)) |
463 | } | 463 | } |
464 | 464 | ||
465 | pub fn krate(&self) -> Option<CrateId> { | 465 | pub fn krate(&self) -> Option<CrateId> { |
@@ -529,7 +529,7 @@ impl Scope { | |||
529 | f(name.clone(), ScopeDef::PerNs(def)); | 529 | f(name.clone(), ScopeDef::PerNs(def)); |
530 | }); | 530 | }); |
531 | if let Some(prelude) = m.crate_def_map.prelude() { | 531 | if let Some(prelude) = m.crate_def_map.prelude() { |
532 | let prelude_def_map = db.crate_def_map(prelude.krate); | 532 | let prelude_def_map = prelude.def_map(db); |
533 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { | 533 | prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { |
534 | let seen_tuple = (name.clone(), def); | 534 | let seen_tuple = (name.clone(), def); |
535 | if !seen.contains(&seen_tuple) { | 535 | if !seen.contains(&seen_tuple) { |
@@ -633,7 +633,7 @@ pub trait HasResolver: Copy { | |||
633 | 633 | ||
634 | impl HasResolver for ModuleId { | 634 | impl HasResolver for ModuleId { |
635 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | 635 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { |
636 | let def_map = db.crate_def_map(self.krate); | 636 | let def_map = self.def_map(db); |
637 | Resolver::default().push_module_scope(def_map, self.local_id) | 637 | Resolver::default().push_module_scope(def_map, self.local_id) |
638 | } | 638 | } |
639 | } | 639 | } |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index 4ff219fb7..c4e36eda5 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet; | |||
15 | use syntax::{TextRange, TextSize}; | 15 | use syntax::{TextRange, TextSize}; |
16 | use test_utils::extract_annotations; | 16 | use test_utils::extract_annotations; |
17 | 17 | ||
18 | use crate::{db::DefDatabase, ModuleDefId}; | 18 | use crate::{db::DefDatabase, ModuleDefId, ModuleId}; |
19 | 19 | ||
20 | #[salsa::database( | 20 | #[salsa::database( |
21 | base_db::SourceDatabaseExtStorage, | 21 | base_db::SourceDatabaseExtStorage, |
@@ -72,12 +72,12 @@ impl FileLoader for TestDB { | |||
72 | } | 72 | } |
73 | 73 | ||
74 | impl TestDB { | 74 | impl TestDB { |
75 | pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId { | 75 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { |
76 | for &krate in self.relevant_crates(file_id).iter() { | 76 | for &krate in self.relevant_crates(file_id).iter() { |
77 | let crate_def_map = self.crate_def_map(krate); | 77 | let crate_def_map = self.crate_def_map(krate); |
78 | for (local_id, data) in crate_def_map.modules() { | 78 | for (local_id, data) in crate_def_map.modules() { |
79 | if data.origin.file_id() == Some(file_id) { | 79 | if data.origin.file_id() == Some(file_id) { |
80 | return crate::ModuleId { krate, local_id }; | 80 | return crate_def_map.module_id(local_id); |
81 | } | 81 | } |
82 | } | 82 | } |
83 | } | 83 | } |
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 3134fa43d..e79a91102 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -103,7 +103,7 @@ impl Visibility { | |||
103 | if from_module.krate != to_module.krate { | 103 | if from_module.krate != to_module.krate { |
104 | return false; | 104 | return false; |
105 | } | 105 | } |
106 | let def_map = db.crate_def_map(from_module.krate); | 106 | let def_map = from_module.def_map(db); |
107 | self.is_visible_from_def_map(&def_map, from_module.local_id) | 107 | self.is_visible_from_def_map(&def_map, from_module.local_id) |
108 | } | 108 | } |
109 | 109 | ||