diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/body/tests.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 18 | ||||
-rw-r--r-- | crates/hir_def/src/import_map.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 31 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 45 | ||||
-rw-r--r-- | crates/hir_def/src/lang_item.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 140 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 58 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 37 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 20 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/block.rs | 97 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 23 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 6 |
16 files changed, 435 insertions, 95 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 1b09ff816..c72649c41 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -207,6 +207,7 @@ impl Attrs { | |||
207 | mod_data.definition_source(db).as_ref().map(|src| match src { | 207 | mod_data.definition_source(db).as_ref().map(|src| match src { |
208 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, | 208 | ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, |
209 | ModuleSource::Module(module) => module as &dyn AttrsOwner, | 209 | ModuleSource::Module(module) => module as &dyn AttrsOwner, |
210 | ModuleSource::BlockExpr(block) => block as &dyn AttrsOwner, | ||
210 | }), | 211 | }), |
211 | ), | 212 | ), |
212 | } | 213 | } |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 3b2dd0f6e..2c2c999dd 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -122,7 +122,7 @@ impl Expander { | |||
122 | 122 | ||
123 | let mut err = None; | 123 | let mut err = None; |
124 | let call_id = | 124 | let call_id = |
125 | macro_call.as_call_id_with_errors(db, self.crate_def_map.krate, resolver, &mut |e| { | 125 | macro_call.as_call_id_with_errors(db, self.crate_def_map.krate(), resolver, &mut |e| { |
126 | err.get_or_insert(e); | 126 | err.get_or_insert(e); |
127 | }); | 127 | }); |
128 | let call_id = match call_id { | 128 | let call_id = match call_id { |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index de77d5fc9..2e5d0a01e 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -6,18 +6,24 @@ use crate::{test_db::TestDB, ModuleDefId}; | |||
6 | use super::*; | 6 | use super::*; |
7 | 7 | ||
8 | fn lower(ra_fixture: &str) -> Arc<Body> { | 8 | fn lower(ra_fixture: &str) -> Arc<Body> { |
9 | let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture); | 9 | let db = crate::test_db::TestDB::with_files(ra_fixture); |
10 | 10 | ||
11 | let krate = db.crate_graph().iter().next().unwrap(); | 11 | let krate = db.crate_graph().iter().next().unwrap(); |
12 | let def_map = db.crate_def_map(krate); | 12 | let def_map = db.crate_def_map(krate); |
13 | let module = def_map.modules_for_file(file_id).next().unwrap(); | 13 | let mut fn_def = None; |
14 | let module = &def_map[module]; | 14 | 'outer: for (_, module) in def_map.modules() { |
15 | let fn_def = match module.scope.declarations().next().unwrap() { | 15 | for decl in module.scope.declarations() { |
16 | ModuleDefId::FunctionId(it) => it, | 16 | match decl { |
17 | _ => panic!(), | 17 | ModuleDefId::FunctionId(it) => { |
18 | }; | 18 | fn_def = Some(it); |
19 | break 'outer; | ||
20 | } | ||
21 | _ => {} | ||
22 | } | ||
23 | } | ||
24 | } | ||
19 | 25 | ||
20 | db.body(fn_def.into()) | 26 | db.body(fn_def.unwrap().into()) |
21 | } | 27 | } |
22 | 28 | ||
23 | fn check_diagnostics(ra_fixture: &str) { | 29 | fn check_diagnostics(ra_fixture: &str) { |
@@ -42,6 +48,25 @@ fn main() { n_nuple!(1,2,3); } | |||
42 | } | 48 | } |
43 | 49 | ||
44 | #[test] | 50 | #[test] |
51 | fn macro_resolve() { | ||
52 | // Regression test for a path resolution bug introduced with inner item handling. | ||
53 | lower( | ||
54 | r" | ||
55 | macro_rules! vec { | ||
56 | () => { () }; | ||
57 | ($elem:expr; $n:expr) => { () }; | ||
58 | ($($x:expr),+ $(,)?) => { () }; | ||
59 | } | ||
60 | mod m { | ||
61 | fn outer() { | ||
62 | let _ = vec![FileSet::default(); self.len()]; | ||
63 | } | ||
64 | } | ||
65 | ", | ||
66 | ); | ||
67 | } | ||
68 | |||
69 | #[test] | ||
45 | fn cfg_diagnostics() { | 70 | fn cfg_diagnostics() { |
46 | check_diagnostics( | 71 | check_diagnostics( |
47 | r" | 72 | r" |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 91c8d45cd..a87c80b8a 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, HirFileId}; | 5 | use hir_expand::{db::AstDatabase, AstId, HirFileId}; |
6 | use la_arena::ArenaMap; | 6 | use la_arena::ArenaMap; |
7 | use syntax::SmolStr; | 7 | use syntax::{ast, SmolStr}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
@@ -55,6 +55,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
55 | #[salsa::invoke(DefMap::crate_def_map_query)] | 55 | #[salsa::invoke(DefMap::crate_def_map_query)] |
56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; | 56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; |
57 | 57 | ||
58 | #[salsa::invoke(DefMap::block_def_map_query)] | ||
59 | fn block_def_map(&self, krate: CrateId, block: AstId<ast::BlockExpr>) -> Arc<DefMap>; | ||
60 | |||
58 | #[salsa::invoke(StructData::struct_data_query)] | 61 | #[salsa::invoke(StructData::struct_data_query)] |
59 | fn struct_data(&self, id: StructId) -> Arc<StructData>; | 62 | fn struct_data(&self, id: StructId) -> Arc<StructData>; |
60 | #[salsa::invoke(StructData::union_data_query)] | 63 | #[salsa::invoke(StructData::union_data_query)] |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 422a6eeb4..db2d125ae 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -51,7 +51,7 @@ fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option< | |||
51 | if item == ItemInNs::Types(from.into()) { | 51 | if item == ItemInNs::Types(from.into()) { |
52 | // - if the item is the module we're in, use `self` | 52 | // - if the item is the module we're in, use `self` |
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.modules[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 | if item |
57 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 57 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { |
@@ -111,7 +111,7 @@ fn find_path_inner( | |||
111 | 111 | ||
112 | // - if the item is already in scope, return the name under which it is | 112 | // - if the item is already in scope, return the name under which it is |
113 | let def_map = db.crate_def_map(from.krate); | 113 | let def_map = db.crate_def_map(from.krate); |
114 | let from_scope: &crate::item_scope::ItemScope = &def_map.modules[from.local_id].scope; | 114 | let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope; |
115 | let scope_name = | 115 | let scope_name = |
116 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; | 116 | if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; |
117 | if prefixed.is_none() && scope_name.is_some() { | 117 | if prefixed.is_none() && scope_name.is_some() { |
@@ -123,7 +123,7 @@ fn find_path_inner( | |||
123 | if item | 123 | if item |
124 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { | 124 | == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { |
125 | krate: from.krate, | 125 | krate: from.krate, |
126 | local_id: def_map.root, | 126 | local_id: def_map.root(), |
127 | })) | 127 | })) |
128 | { | 128 | { |
129 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 129 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
@@ -136,7 +136,7 @@ fn find_path_inner( | |||
136 | } | 136 | } |
137 | 137 | ||
138 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude | 138 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude |
139 | for (name, def_id) in &def_map.extern_prelude { | 139 | for (name, def_id) in def_map.extern_prelude() { |
140 | if item == ItemInNs::Types(*def_id) { | 140 | if item == ItemInNs::Types(*def_id) { |
141 | let name = scope_name.unwrap_or_else(|| name.clone()); | 141 | let name = scope_name.unwrap_or_else(|| name.clone()); |
142 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); | 142 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); |
@@ -144,10 +144,10 @@ fn find_path_inner( | |||
144 | } | 144 | } |
145 | 145 | ||
146 | // - if the item is in the prelude, return the name from there | 146 | // - if the item is in the prelude, return the name from there |
147 | if let Some(prelude_module) = def_map.prelude { | 147 | if let Some(prelude_module) = def_map.prelude() { |
148 | let prelude_def_map = db.crate_def_map(prelude_module.krate); | 148 | let prelude_def_map = db.crate_def_map(prelude_module.krate); |
149 | let prelude_scope: &crate::item_scope::ItemScope = | 149 | let prelude_scope: &crate::item_scope::ItemScope = |
150 | &prelude_def_map.modules[prelude_module.local_id].scope; | 150 | &prelude_def_map[prelude_module.local_id].scope; |
151 | if let Some((name, vis)) = prelude_scope.name_of(item) { | 151 | if let Some((name, vis)) = prelude_scope.name_of(item) { |
152 | if vis.is_visible_from(db, from) { | 152 | if vis.is_visible_from(db, from) { |
153 | return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); | 153 | return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); |
@@ -175,7 +175,7 @@ fn find_path_inner( | |||
175 | 175 | ||
176 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 176 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
177 | 177 | ||
178 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; | 178 | let crate_root = ModuleId { local_id: def_map.root(), krate: from.krate }; |
179 | let crate_attrs = db.attrs(crate_root.into()); | 179 | let crate_attrs = db.attrs(crate_root.into()); |
180 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 180 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
181 | let mut best_path = None; | 181 | let mut best_path = None; |
@@ -287,7 +287,7 @@ fn find_local_import_locations( | |||
287 | 287 | ||
288 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all | 288 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all |
289 | // of its (recursive) parent modules. | 289 | // of its (recursive) parent modules. |
290 | let data = &def_map.modules[from.local_id]; | 290 | let data = &def_map[from.local_id]; |
291 | let mut worklist = data | 291 | let mut worklist = data |
292 | .children | 292 | .children |
293 | .values() | 293 | .values() |
@@ -296,7 +296,7 @@ fn find_local_import_locations( | |||
296 | let mut parent = data.parent; | 296 | let mut parent = data.parent; |
297 | while let Some(p) = parent { | 297 | while let Some(p) = parent { |
298 | worklist.push(ModuleId { krate: from.krate, local_id: p }); | 298 | worklist.push(ModuleId { krate: from.krate, local_id: p }); |
299 | parent = def_map.modules[p].parent; | 299 | parent = def_map[p].parent; |
300 | } | 300 | } |
301 | 301 | ||
302 | let mut seen: FxHashSet<_> = FxHashSet::default(); | 302 | let mut seen: FxHashSet<_> = FxHashSet::default(); |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index fac0de90c..0251d016b 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 = ModuleId { krate, local_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; |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ff62928df..b8d7608e7 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -21,6 +21,7 @@ use hir_expand::{ | |||
21 | HirFileId, InFile, | 21 | HirFileId, InFile, |
22 | }; | 22 | }; |
23 | use la_arena::{Arena, Idx, RawIdx}; | 23 | use la_arena::{Arena, Idx, RawIdx}; |
24 | use profile::Count; | ||
24 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
25 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
26 | use syntax::{ast, match_ast}; | 27 | use syntax::{ast, match_ast}; |
@@ -67,15 +68,16 @@ impl GenericParamsId { | |||
67 | /// The item tree of a source file. | 68 | /// The item tree of a source file. |
68 | #[derive(Debug, Eq, PartialEq)] | 69 | #[derive(Debug, Eq, PartialEq)] |
69 | pub struct ItemTree { | 70 | pub struct ItemTree { |
71 | _c: Count<Self>, | ||
72 | |||
70 | top_level: SmallVec<[ModItem; 1]>, | 73 | top_level: SmallVec<[ModItem; 1]>, |
71 | attrs: FxHashMap<AttrOwner, RawAttrs>, | 74 | attrs: FxHashMap<AttrOwner, RawAttrs>, |
72 | inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, | ||
73 | 75 | ||
74 | data: Option<Box<ItemTreeData>>, | 76 | data: Option<Box<ItemTreeData>>, |
75 | } | 77 | } |
76 | 78 | ||
77 | impl ItemTree { | 79 | impl ItemTree { |
78 | pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { | 80 | pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { |
79 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); | 81 | let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); |
80 | 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) { |
81 | node | 83 | node |
@@ -118,9 +120,9 @@ impl ItemTree { | |||
118 | 120 | ||
119 | fn empty() -> Self { | 121 | fn empty() -> Self { |
120 | Self { | 122 | Self { |
123 | _c: Count::new(), | ||
121 | top_level: Default::default(), | 124 | top_level: Default::default(), |
122 | attrs: Default::default(), | 125 | attrs: Default::default(), |
123 | inner_items: Default::default(), | ||
124 | data: Default::default(), | 126 | data: Default::default(), |
125 | } | 127 | } |
126 | } | 128 | } |
@@ -147,6 +149,7 @@ impl ItemTree { | |||
147 | macro_defs, | 149 | macro_defs, |
148 | vis, | 150 | vis, |
149 | generics, | 151 | generics, |
152 | inner_items, | ||
150 | } = &mut **data; | 153 | } = &mut **data; |
151 | 154 | ||
152 | imports.shrink_to_fit(); | 155 | imports.shrink_to_fit(); |
@@ -169,6 +172,8 @@ impl ItemTree { | |||
169 | 172 | ||
170 | vis.arena.shrink_to_fit(); | 173 | vis.arena.shrink_to_fit(); |
171 | generics.arena.shrink_to_fit(); | 174 | generics.arena.shrink_to_fit(); |
175 | |||
176 | inner_items.shrink_to_fit(); | ||
172 | } | 177 | } |
173 | } | 178 | } |
174 | 179 | ||
@@ -191,16 +196,18 @@ impl ItemTree { | |||
191 | self.raw_attrs(of).clone().filter(db, krate) | 196 | self.raw_attrs(of).clone().filter(db, krate) |
192 | } | 197 | } |
193 | 198 | ||
194 | /// Returns the lowered inner items that `ast` corresponds to. | 199 | pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { |
195 | /// | 200 | match &self.data { |
196 | /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered | 201 | Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(), |
197 | /// to multiple items in the `ItemTree`. | 202 | None => None.into_iter().flatten(), |
198 | pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] { | 203 | } |
199 | &self.inner_items[&ast] | ||
200 | } | 204 | } |
201 | 205 | ||
202 | pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { | 206 | pub fn inner_items_of_block(&self, block: FileAstId<ast::BlockExpr>) -> &[ModItem] { |
203 | self.inner_items.values().flatten().copied() | 207 | match &self.data { |
208 | Some(data) => data.inner_items.get(&block).map(|it| &**it).unwrap_or(&[]), | ||
209 | None => &[], | ||
210 | } | ||
204 | } | 211 | } |
205 | 212 | ||
206 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { | 213 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { |
@@ -297,6 +304,8 @@ struct ItemTreeData { | |||
297 | 304 | ||
298 | vis: ItemVisibilities, | 305 | vis: ItemVisibilities, |
299 | generics: GenericParamsStorage, | 306 | generics: GenericParamsStorage, |
307 | |||
308 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | ||
300 | } | 309 | } |
301 | 310 | ||
302 | #[derive(Debug, Eq, PartialEq, Hash)] | 311 | #[derive(Debug, Eq, PartialEq, Hash)] |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5e71ca42c..ce470fc3b 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId} | |||
6 | use smallvec::SmallVec; | 6 | use smallvec::SmallVec; |
7 | use syntax::{ | 7 | use syntax::{ |
8 | ast::{self, ModuleItemOwner}, | 8 | ast::{self, ModuleItemOwner}, |
9 | SyntaxNode, | 9 | SyntaxNode, WalkEvent, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -37,7 +37,6 @@ pub(super) struct Ctx { | |||
37 | file: HirFileId, | 37 | file: HirFileId, |
38 | source_ast_id_map: Arc<AstIdMap>, | 38 | source_ast_id_map: Arc<AstIdMap>, |
39 | body_ctx: crate::body::LowerCtx, | 39 | body_ctx: crate::body::LowerCtx, |
40 | inner_items: Vec<ModItem>, | ||
41 | forced_visibility: Option<RawVisibilityId>, | 40 | forced_visibility: Option<RawVisibilityId>, |
42 | } | 41 | } |
43 | 42 | ||
@@ -49,7 +48,6 @@ impl Ctx { | |||
49 | file, | 48 | file, |
50 | source_ast_id_map: db.ast_id_map(file), | 49 | source_ast_id_map: db.ast_id_map(file), |
51 | body_ctx: crate::body::LowerCtx::new(db, file), | 50 | body_ctx: crate::body::LowerCtx::new(db, file), |
52 | inner_items: Vec::new(), | ||
53 | forced_visibility: None, | 51 | forced_visibility: None, |
54 | } | 52 | } |
55 | } | 53 | } |
@@ -73,8 +71,6 @@ impl Ctx { | |||
73 | } | 71 | } |
74 | 72 | ||
75 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { | 73 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { |
76 | assert!(inner || self.inner_items.is_empty()); | ||
77 | |||
78 | // Collect inner items for 1-to-1-lowered items. | 74 | // Collect inner items for 1-to-1-lowered items. |
79 | match item { | 75 | match item { |
80 | ast::Item::Struct(_) | 76 | ast::Item::Struct(_) |
@@ -150,14 +146,37 @@ impl Ctx { | |||
150 | 146 | ||
151 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 147 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
152 | let forced_vis = self.forced_visibility.take(); | 148 | let forced_vis = self.forced_visibility.take(); |
153 | let mut inner_items = mem::take(&mut self.tree.inner_items); | 149 | |
154 | inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( | 150 | let mut block_stack = Vec::new(); |
155 | |item| { | 151 | for event in container.preorder().skip(1) { |
156 | let ast_id = self.source_ast_id_map.ast_id(&item); | 152 | match event { |
157 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | 153 | WalkEvent::Enter(node) => { |
158 | }, | 154 | match_ast! { |
159 | )); | 155 | match node { |
160 | self.tree.inner_items = inner_items; | 156 | ast::BlockExpr(block) => { |
157 | block_stack.push(self.source_ast_id_map.ast_id(&block)); | ||
158 | }, | ||
159 | ast::Item(item) => { | ||
160 | let mod_items = self.lower_mod_item(&item, true); | ||
161 | let current_block = block_stack.last(); | ||
162 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | ||
163 | if !mod_items.0.is_empty() { | ||
164 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | ||
165 | } | ||
166 | } | ||
167 | }, | ||
168 | _ => {} | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | WalkEvent::Leave(node) => { | ||
173 | if ast::BlockExpr::cast(node).is_some() { | ||
174 | block_stack.pop(); | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
161 | self.forced_visibility = forced_vis; | 180 | self.forced_visibility = forced_vis; |
162 | } | 181 | } |
163 | 182 | ||
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 30188b740..9e90f745c 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs | |||
@@ -84,7 +84,7 @@ impl LangItems { | |||
84 | 84 | ||
85 | let crate_def_map = db.crate_def_map(krate); | 85 | let crate_def_map = db.crate_def_map(krate); |
86 | 86 | ||
87 | for (_, module_data) in crate_def_map.modules.iter() { | 87 | for (_, module_data) in crate_def_map.modules() { |
88 | for impl_def in module_data.scope.impls() { | 88 | for impl_def in module_data.scope.impls() { |
89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) | 89 | lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) |
90 | } | 90 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 769a557ad..bd3ea9b8b 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -59,9 +59,10 @@ use std::sync::Arc; | |||
59 | use base_db::{CrateId, Edition, FileId}; | 59 | use base_db::{CrateId, Edition, FileId}; |
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | 60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; |
61 | use la_arena::Arena; | 61 | use la_arena::Arena; |
62 | use profile::Count; | ||
62 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
63 | use stdx::format_to; | 64 | use stdx::format_to; |
64 | use syntax::ast; | 65 | use syntax::{ast, AstNode}; |
65 | 66 | ||
66 | use crate::{ | 67 | use crate::{ |
67 | db::DefDatabase, | 68 | db::DefDatabase, |
@@ -75,14 +76,16 @@ use crate::{ | |||
75 | /// Contains all top-level defs from a macro-expanded crate | 76 | /// Contains all top-level defs from a macro-expanded crate |
76 | #[derive(Debug, PartialEq, Eq)] | 77 | #[derive(Debug, PartialEq, Eq)] |
77 | pub struct DefMap { | 78 | pub struct DefMap { |
78 | pub root: LocalModuleId, | 79 | _c: Count<Self>, |
79 | pub modules: Arena<ModuleData>, | 80 | parent: Option<Arc<DefMap>>, |
80 | pub(crate) krate: CrateId, | 81 | root: LocalModuleId, |
82 | modules: Arena<ModuleData>, | ||
83 | krate: CrateId, | ||
81 | /// The prelude module for this crate. This either comes from an import | 84 | /// The prelude module for this crate. This either comes from an import |
82 | /// marked with the `prelude_import` attribute, or (in the normal case) from | 85 | /// marked with the `prelude_import` attribute, or (in the normal case) from |
83 | /// a dependency (`std` or `core`). | 86 | /// a dependency (`std` or `core`). |
84 | pub(crate) prelude: Option<ModuleId>, | 87 | prelude: Option<ModuleId>, |
85 | pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>, | 88 | extern_prelude: FxHashMap<Name, ModuleDefId>, |
86 | 89 | ||
87 | edition: Edition, | 90 | edition: Edition, |
88 | diagnostics: Vec<DefDiagnostic>, | 91 | diagnostics: Vec<DefDiagnostic>, |
@@ -109,6 +112,10 @@ pub enum ModuleOrigin { | |||
109 | Inline { | 112 | Inline { |
110 | definition: AstId<ast::Module>, | 113 | definition: AstId<ast::Module>, |
111 | }, | 114 | }, |
115 | /// Pseudo-module introduced by a block scope (contains only inner items). | ||
116 | BlockExpr { | ||
117 | block: AstId<ast::BlockExpr>, | ||
118 | }, | ||
112 | } | 119 | } |
113 | 120 | ||
114 | impl Default for ModuleOrigin { | 121 | impl Default for ModuleOrigin { |
@@ -122,7 +129,7 @@ impl ModuleOrigin { | |||
122 | match self { | 129 | match self { |
123 | ModuleOrigin::File { declaration: module, .. } | 130 | ModuleOrigin::File { declaration: module, .. } |
124 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), | 131 | | ModuleOrigin::Inline { definition: module, .. } => Some(*module), |
125 | ModuleOrigin::CrateRoot { .. } => None, | 132 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, |
126 | } | 133 | } |
127 | } | 134 | } |
128 | 135 | ||
@@ -137,7 +144,7 @@ impl ModuleOrigin { | |||
137 | 144 | ||
138 | pub fn is_inline(&self) -> bool { | 145 | pub fn is_inline(&self) -> bool { |
139 | match self { | 146 | match self { |
140 | ModuleOrigin::Inline { .. } => true, | 147 | ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true, |
141 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, | 148 | ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, |
142 | } | 149 | } |
143 | } | 150 | } |
@@ -155,6 +162,9 @@ impl ModuleOrigin { | |||
155 | definition.file_id, | 162 | definition.file_id, |
156 | ModuleSource::Module(definition.to_node(db.upcast())), | 163 | ModuleSource::Module(definition.to_node(db.upcast())), |
157 | ), | 164 | ), |
165 | ModuleOrigin::BlockExpr { block } => { | ||
166 | InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast()))) | ||
167 | } | ||
158 | } | 168 | } |
159 | } | 169 | } |
160 | } | 170 | } |
@@ -174,24 +184,51 @@ impl DefMap { | |||
174 | let _p = profile::span("crate_def_map_query").detail(|| { | 184 | let _p = profile::span("crate_def_map_query").detail(|| { |
175 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() | 185 | db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() |
176 | }); | 186 | }); |
177 | let def_map = { | 187 | let edition = db.crate_graph()[krate].edition; |
178 | let edition = db.crate_graph()[krate].edition; | 188 | let def_map = DefMap::empty(krate, edition); |
179 | let mut modules: Arena<ModuleData> = Arena::default(); | 189 | let def_map = collector::collect_defs(db, def_map, None); |
180 | let root = modules.alloc(ModuleData::default()); | ||
181 | DefMap { | ||
182 | krate, | ||
183 | edition, | ||
184 | extern_prelude: FxHashMap::default(), | ||
185 | prelude: None, | ||
186 | root, | ||
187 | modules, | ||
188 | diagnostics: Vec::new(), | ||
189 | } | ||
190 | }; | ||
191 | let def_map = collector::collect_defs(db, def_map); | ||
192 | Arc::new(def_map) | 190 | Arc::new(def_map) |
193 | } | 191 | } |
194 | 192 | ||
193 | pub(crate) fn block_def_map_query( | ||
194 | db: &dyn DefDatabase, | ||
195 | krate: CrateId, | ||
196 | block: AstId<ast::BlockExpr>, | ||
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 | |||
201 | let parent = parent_def_map(db, krate, block); | ||
202 | |||
203 | if block_items.is_empty() { | ||
204 | // If there are no inner items, nothing new is brought into scope, so we can just return | ||
205 | // the parent DefMap. This keeps DefMap parent chains short. | ||
206 | return parent; | ||
207 | } | ||
208 | |||
209 | let mut def_map = DefMap::empty(krate, parent.edition); | ||
210 | def_map.parent = Some(parent); | ||
211 | |||
212 | let def_map = collector::collect_defs(db, def_map, Some(block.value)); | ||
213 | Arc::new(def_map) | ||
214 | } | ||
215 | |||
216 | fn empty(krate: CrateId, edition: Edition) -> DefMap { | ||
217 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
218 | let root = modules.alloc(ModuleData::default()); | ||
219 | DefMap { | ||
220 | _c: Count::new(), | ||
221 | parent: None, | ||
222 | krate, | ||
223 | edition, | ||
224 | extern_prelude: FxHashMap::default(), | ||
225 | prelude: None, | ||
226 | root, | ||
227 | modules, | ||
228 | diagnostics: Vec::new(), | ||
229 | } | ||
230 | } | ||
231 | |||
195 | pub fn add_diagnostics( | 232 | pub fn add_diagnostics( |
196 | &self, | 233 | &self, |
197 | db: &dyn DefDatabase, | 234 | db: &dyn DefDatabase, |
@@ -208,6 +245,26 @@ impl DefMap { | |||
208 | .map(|(id, _data)| id) | 245 | .map(|(id, _data)| id) |
209 | } | 246 | } |
210 | 247 | ||
248 | pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ { | ||
249 | self.modules.iter() | ||
250 | } | ||
251 | |||
252 | pub fn root(&self) -> LocalModuleId { | ||
253 | self.root | ||
254 | } | ||
255 | |||
256 | pub(crate) fn krate(&self) -> CrateId { | ||
257 | self.krate | ||
258 | } | ||
259 | |||
260 | pub(crate) fn prelude(&self) -> Option<ModuleId> { | ||
261 | self.prelude | ||
262 | } | ||
263 | |||
264 | pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, &ModuleDefId)> + '_ { | ||
265 | self.extern_prelude.iter() | ||
266 | } | ||
267 | |||
211 | pub(crate) fn resolve_path( | 268 | pub(crate) fn resolve_path( |
212 | &self, | 269 | &self, |
213 | db: &dyn DefDatabase, | 270 | db: &dyn DefDatabase, |
@@ -224,7 +281,12 @@ impl DefMap { | |||
224 | // even), as this should be a great debugging aid. | 281 | // even), as this should be a great debugging aid. |
225 | pub fn dump(&self) -> String { | 282 | pub fn dump(&self) -> String { |
226 | let mut buf = String::new(); | 283 | let mut buf = String::new(); |
227 | go(&mut buf, self, "crate", self.root); | 284 | let mut current_map = self; |
285 | while let Some(parent) = ¤t_map.parent { | ||
286 | go(&mut buf, current_map, "block scope", current_map.root); | ||
287 | current_map = &**parent; | ||
288 | } | ||
289 | go(&mut buf, current_map, "crate", current_map.root); | ||
228 | return buf; | 290 | return buf; |
229 | 291 | ||
230 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { | 292 | fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { |
@@ -276,10 +338,40 @@ impl ModuleData { | |||
276 | } | 338 | } |
277 | } | 339 | } |
278 | 340 | ||
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 | |||
279 | #[derive(Debug, Clone, PartialEq, Eq)] | 370 | #[derive(Debug, Clone, PartialEq, Eq)] |
280 | pub enum ModuleSource { | 371 | pub enum ModuleSource { |
281 | SourceFile(ast::SourceFile), | 372 | SourceFile(ast::SourceFile), |
282 | Module(ast::Module), | 373 | Module(ast::Module), |
374 | BlockExpr(ast::BlockExpr), | ||
283 | } | 375 | } |
284 | 376 | ||
285 | mod diagnostics { | 377 | mod diagnostics { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 61da56340..cd68efbe6 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -45,7 +45,11 @@ const GLOB_RECURSION_LIMIT: usize = 100; | |||
45 | const EXPANSION_DEPTH_LIMIT: usize = 128; | 45 | const EXPANSION_DEPTH_LIMIT: usize = 128; |
46 | const FIXED_POINT_LIMIT: usize = 8192; | 46 | const FIXED_POINT_LIMIT: usize = 8192; |
47 | 47 | ||
48 | pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap) -> DefMap { | 48 | pub(super) fn collect_defs( |
49 | db: &dyn DefDatabase, | ||
50 | mut def_map: DefMap, | ||
51 | block: Option<FileAstId<ast::BlockExpr>>, | ||
52 | ) -> DefMap { | ||
49 | let crate_graph = db.crate_graph(); | 53 | let crate_graph = db.crate_graph(); |
50 | 54 | ||
51 | // populate external prelude | 55 | // populate external prelude |
@@ -93,6 +97,14 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap) -> DefMap | |||
93 | exports_proc_macros: false, | 97 | exports_proc_macros: false, |
94 | from_glob_import: Default::default(), | 98 | from_glob_import: Default::default(), |
95 | }; | 99 | }; |
100 | match block { | ||
101 | Some(block) => { | ||
102 | collector.seed_with_inner(block); | ||
103 | } | ||
104 | None => { | ||
105 | collector.seed_with_top_level(); | ||
106 | } | ||
107 | } | ||
96 | collector.collect(); | 108 | collector.collect(); |
97 | collector.finish() | 109 | collector.finish() |
98 | } | 110 | } |
@@ -228,7 +240,7 @@ struct DefCollector<'a> { | |||
228 | } | 240 | } |
229 | 241 | ||
230 | impl DefCollector<'_> { | 242 | impl DefCollector<'_> { |
231 | fn collect(&mut self) { | 243 | fn seed_with_top_level(&mut self) { |
232 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; | 244 | 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()); | 245 | let item_tree = self.db.item_tree(file_id.into()); |
234 | let module_id = self.def_map.root; | 246 | let module_id = self.def_map.root; |
@@ -248,7 +260,31 @@ impl DefCollector<'_> { | |||
248 | } | 260 | } |
249 | .collect(item_tree.top_level_items()); | 261 | .collect(item_tree.top_level_items()); |
250 | } | 262 | } |
263 | } | ||
264 | |||
265 | fn seed_with_inner(&mut self, block: FileAstId<ast::BlockExpr>) { | ||
266 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; | ||
267 | let item_tree = self.db.item_tree(file_id.into()); | ||
268 | let module_id = self.def_map.root; | ||
269 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; | ||
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: file_id.into(), | ||
280 | item_tree: &item_tree, | ||
281 | mod_dir: ModDir::root(), | ||
282 | } | ||
283 | .collect(item_tree.inner_items_of_block(block)); | ||
284 | } | ||
285 | } | ||
251 | 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 { |
@@ -1470,7 +1506,6 @@ impl ModCollector<'_, '_> { | |||
1470 | mod tests { | 1506 | mod tests { |
1471 | use crate::{db::DefDatabase, test_db::TestDB}; | 1507 | use crate::{db::DefDatabase, test_db::TestDB}; |
1472 | use base_db::{fixture::WithFixture, SourceDatabase}; | 1508 | use base_db::{fixture::WithFixture, SourceDatabase}; |
1473 | use la_arena::Arena; | ||
1474 | 1509 | ||
1475 | use super::*; | 1510 | use super::*; |
1476 | 1511 | ||
@@ -1489,6 +1524,7 @@ mod tests { | |||
1489 | exports_proc_macros: false, | 1524 | exports_proc_macros: false, |
1490 | from_glob_import: Default::default(), | 1525 | from_glob_import: Default::default(), |
1491 | }; | 1526 | }; |
1527 | collector.seed_with_top_level(); | ||
1492 | collector.collect(); | 1528 | collector.collect(); |
1493 | collector.def_map | 1529 | collector.def_map |
1494 | } | 1530 | } |
@@ -1497,20 +1533,8 @@ mod tests { | |||
1497 | let (db, _file_id) = TestDB::with_single_file(&code); | 1533 | let (db, _file_id) = TestDB::with_single_file(&code); |
1498 | let krate = db.test_crate(); | 1534 | let krate = db.test_crate(); |
1499 | 1535 | ||
1500 | let def_map = { | 1536 | let edition = db.crate_graph()[krate].edition; |
1501 | let edition = db.crate_graph()[krate].edition; | 1537 | let def_map = DefMap::empty(krate, edition); |
1502 | let mut modules: Arena<ModuleData> = Arena::default(); | ||
1503 | let root = modules.alloc(ModuleData::default()); | ||
1504 | DefMap { | ||
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) | 1538 | do_collect_defs(&db, def_map) |
1515 | } | 1539 | } |
1516 | 1540 | ||
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 096a7d0ac..ec90f4e65 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -104,6 +104,43 @@ impl DefMap { | |||
104 | path: &ModPath, | 104 | path: &ModPath, |
105 | shadow: BuiltinShadowMode, | 105 | shadow: BuiltinShadowMode, |
106 | ) -> ResolvePathResult { | 106 | ) -> ResolvePathResult { |
107 | let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); | ||
108 | result.segment_index = Some(usize::max_value()); | ||
109 | |||
110 | let mut current_map = self; | ||
111 | loop { | ||
112 | let new = current_map.resolve_path_fp_with_macro_single( | ||
113 | db, | ||
114 | mode, | ||
115 | original_module, | ||
116 | path, | ||
117 | shadow, | ||
118 | ); | ||
119 | |||
120 | // Merge `new` into `result`. | ||
121 | result.resolved_def = result.resolved_def.or(new.resolved_def); | ||
122 | if result.reached_fixedpoint == ReachedFixedPoint::No { | ||
123 | result.reached_fixedpoint = new.reached_fixedpoint; | ||
124 | } | ||
125 | // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates? | ||
126 | result.krate = result.krate.or(new.krate); | ||
127 | result.segment_index = result.segment_index.min(new.segment_index); | ||
128 | |||
129 | match ¤t_map.parent { | ||
130 | Some(map) => current_map = map, | ||
131 | None => return result, | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | pub(super) fn resolve_path_fp_with_macro_single( | ||
137 | &self, | ||
138 | db: &dyn DefDatabase, | ||
139 | mode: ResolveMode, | ||
140 | original_module: LocalModuleId, | ||
141 | path: &ModPath, | ||
142 | shadow: BuiltinShadowMode, | ||
143 | ) -> ResolvePathResult { | ||
107 | let mut segments = path.segments.iter().enumerate(); | 144 | let mut segments = path.segments.iter().enumerate(); |
108 | let mut curr_per_ns: PerNs = match path.kind { | 145 | let mut curr_per_ns: PerNs = match path.kind { |
109 | PathKind::DollarCrate(krate) => { | 146 | PathKind::DollarCrate(krate) => { |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 723481c36..73e3a4702 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -4,11 +4,13 @@ mod macros; | |||
4 | mod mod_resolution; | 4 | mod mod_resolution; |
5 | mod diagnostics; | 5 | mod diagnostics; |
6 | mod primitives; | 6 | mod primitives; |
7 | mod block; | ||
7 | 8 | ||
8 | use std::sync::Arc; | 9 | use std::sync::Arc; |
9 | 10 | ||
10 | use base_db::{fixture::WithFixture, SourceDatabase}; | 11 | use base_db::{fixture::WithFixture, SourceDatabase}; |
11 | use expect_test::{expect, Expect}; | 12 | use expect_test::{expect, Expect}; |
13 | use hir_expand::db::AstDatabase; | ||
12 | use test_utils::mark; | 14 | use test_utils::mark; |
13 | 15 | ||
14 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
@@ -19,12 +21,30 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | |||
19 | db.crate_def_map(krate) | 21 | db.crate_def_map(krate) |
20 | } | 22 | } |
21 | 23 | ||
24 | fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { | ||
25 | let (db, position) = TestDB::with_position(ra_fixture); | ||
26 | let module = db.module_for_file(position.file_id); | ||
27 | let ast_map = db.ast_id_map(position.file_id.into()); | ||
28 | let ast = db.parse(position.file_id); | ||
29 | let block: ast::BlockExpr = | ||
30 | syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap(); | ||
31 | let block_id = ast_map.ast_id(&block); | ||
32 | |||
33 | db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id)) | ||
34 | } | ||
35 | |||
22 | fn check(ra_fixture: &str, expect: Expect) { | 36 | fn check(ra_fixture: &str, expect: Expect) { |
23 | let def_map = compute_crate_def_map(ra_fixture); | 37 | let def_map = compute_crate_def_map(ra_fixture); |
24 | let actual = def_map.dump(); | 38 | let actual = def_map.dump(); |
25 | expect.assert_eq(&actual); | 39 | expect.assert_eq(&actual); |
26 | } | 40 | } |
27 | 41 | ||
42 | fn check_at(ra_fixture: &str, expect: Expect) { | ||
43 | let def_map = compute_block_def_map(ra_fixture); | ||
44 | let actual = def_map.dump(); | ||
45 | expect.assert_eq(&actual); | ||
46 | } | ||
47 | |||
28 | #[test] | 48 | #[test] |
29 | fn crate_def_map_smoke_test() { | 49 | fn crate_def_map_smoke_test() { |
30 | check( | 50 | check( |
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs new file mode 100644 index 000000000..01d6326a7 --- /dev/null +++ b/crates/hir_def/src/nameres/tests/block.rs | |||
@@ -0,0 +1,97 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn inner_item_smoke() { | ||
5 | check_at( | ||
6 | r#" | ||
7 | struct inner {} | ||
8 | fn outer() { | ||
9 | $0 | ||
10 | fn inner() {} | ||
11 | } | ||
12 | "#, | ||
13 | expect![[r#" | ||
14 | block scope | ||
15 | inner: v | ||
16 | crate | ||
17 | inner: t | ||
18 | outer: v | ||
19 | "#]], | ||
20 | ); | ||
21 | } | ||
22 | |||
23 | #[test] | ||
24 | fn use_from_crate() { | ||
25 | check_at( | ||
26 | r#" | ||
27 | struct Struct; | ||
28 | fn outer() { | ||
29 | use Struct; | ||
30 | use crate::Struct as CrateStruct; | ||
31 | use self::Struct as SelfStruct; | ||
32 | $0 | ||
33 | } | ||
34 | "#, | ||
35 | expect![[r#" | ||
36 | block scope | ||
37 | CrateStruct: t v | ||
38 | SelfStruct: t v | ||
39 | Struct: t v | ||
40 | crate | ||
41 | Struct: t v | ||
42 | outer: v | ||
43 | "#]], | ||
44 | ); | ||
45 | } | ||
46 | |||
47 | #[test] | ||
48 | fn merge_namespaces() { | ||
49 | check_at( | ||
50 | r#" | ||
51 | struct name {} | ||
52 | fn outer() { | ||
53 | fn name() {} | ||
54 | |||
55 | use name as imported; // should import both `name`s | ||
56 | |||
57 | $0 | ||
58 | } | ||
59 | "#, | ||
60 | expect![[r#" | ||
61 | block scope | ||
62 | imported: t v | ||
63 | name: v | ||
64 | crate | ||
65 | name: t | ||
66 | outer: v | ||
67 | "#]], | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | #[test] | ||
72 | fn nested_blocks() { | ||
73 | check_at( | ||
74 | r#" | ||
75 | fn outer() { | ||
76 | struct inner1 {} | ||
77 | fn inner() { | ||
78 | use inner1; | ||
79 | use outer; | ||
80 | fn inner2() {} | ||
81 | $0 | ||
82 | } | ||
83 | } | ||
84 | "#, | ||
85 | expect![[r#" | ||
86 | block scope | ||
87 | inner1: t | ||
88 | inner2: v | ||
89 | outer: v | ||
90 | block scope | ||
91 | inner: v | ||
92 | inner1: t | ||
93 | crate | ||
94 | outer: v | ||
95 | "#]], | ||
96 | ); | ||
97 | } | ||
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a505bf2be..b2f577649 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -146,6 +146,19 @@ impl Resolver { | |||
146 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) | 146 | self.resolve_module_path(db, path, BuiltinShadowMode::Module) |
147 | } | 147 | } |
148 | 148 | ||
149 | pub fn resolve_module_path_in_trait_items( | ||
150 | &self, | ||
151 | db: &dyn DefDatabase, | ||
152 | path: &ModPath, | ||
153 | ) -> Option<TraitId> { | ||
154 | let (item_map, module) = self.module_scope()?; | ||
155 | let (module_res, ..) = item_map.resolve_path(db, module, &path, BuiltinShadowMode::Module); | ||
156 | match module_res.take_types()? { | ||
157 | ModuleDefId::TraitId(it) => Some(it), | ||
158 | _ => None, | ||
159 | } | ||
160 | } | ||
161 | |||
149 | pub fn resolve_path_in_type_ns( | 162 | pub fn resolve_path_in_type_ns( |
150 | &self, | 163 | &self, |
151 | db: &dyn DefDatabase, | 164 | db: &dyn DefDatabase, |
@@ -416,7 +429,7 @@ impl Resolver { | |||
416 | let mut traits = FxHashSet::default(); | 429 | let mut traits = FxHashSet::default(); |
417 | for scope in &self.scopes { | 430 | for scope in &self.scopes { |
418 | if let Scope::ModuleScope(m) = scope { | 431 | if let Scope::ModuleScope(m) = scope { |
419 | if let Some(prelude) = m.crate_def_map.prelude { | 432 | if let Some(prelude) = m.crate_def_map.prelude() { |
420 | let prelude_def_map = db.crate_def_map(prelude.krate); | 433 | let prelude_def_map = db.crate_def_map(prelude.krate); |
421 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); | 434 | traits.extend(prelude_def_map[prelude.local_id].scope.traits()); |
422 | } | 435 | } |
@@ -446,11 +459,11 @@ impl Resolver { | |||
446 | 459 | ||
447 | pub fn module(&self) -> Option<ModuleId> { | 460 | pub fn module(&self) -> Option<ModuleId> { |
448 | let (def_map, local_id) = self.module_scope()?; | 461 | let (def_map, local_id) = self.module_scope()?; |
449 | Some(ModuleId { krate: def_map.krate, local_id }) | 462 | Some(ModuleId { krate: def_map.krate(), local_id }) |
450 | } | 463 | } |
451 | 464 | ||
452 | pub fn krate(&self) -> Option<CrateId> { | 465 | pub fn krate(&self) -> Option<CrateId> { |
453 | self.module_scope().map(|t| t.0.krate) | 466 | self.module_scope().map(|t| t.0.krate()) |
454 | } | 467 | } |
455 | 468 | ||
456 | pub fn where_predicates_in_scope<'a>( | 469 | pub fn where_predicates_in_scope<'a>( |
@@ -509,13 +522,13 @@ impl Scope { | |||
509 | seen.insert((name.clone(), scope)); | 522 | seen.insert((name.clone(), scope)); |
510 | f(name.clone(), ScopeDef::PerNs(scope)); | 523 | f(name.clone(), ScopeDef::PerNs(scope)); |
511 | }); | 524 | }); |
512 | m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { | 525 | m.crate_def_map.extern_prelude().for_each(|(name, &def)| { |
513 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); | 526 | f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); |
514 | }); | 527 | }); |
515 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { | 528 | BUILTIN_SCOPE.iter().for_each(|(name, &def)| { |
516 | f(name.clone(), ScopeDef::PerNs(def)); | 529 | f(name.clone(), ScopeDef::PerNs(def)); |
517 | }); | 530 | }); |
518 | if let Some(prelude) = m.crate_def_map.prelude { | 531 | if let Some(prelude) = m.crate_def_map.prelude() { |
519 | let prelude_def_map = db.crate_def_map(prelude.krate); | 532 | let prelude_def_map = db.crate_def_map(prelude.krate); |
520 | 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)| { |
521 | let seen_tuple = (name.clone(), def); | 534 | let seen_tuple = (name.clone(), def); |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index 574c0201a..4ff219fb7 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -75,7 +75,7 @@ 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) -> crate::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.iter() { | 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::ModuleId { krate, local_id }; |
81 | } | 81 | } |
@@ -110,7 +110,7 @@ impl TestDB { | |||
110 | let crate_graph = self.crate_graph(); | 110 | let crate_graph = self.crate_graph(); |
111 | for krate in crate_graph.iter() { | 111 | for krate in crate_graph.iter() { |
112 | let crate_def_map = self.crate_def_map(krate); | 112 | let crate_def_map = self.crate_def_map(krate); |
113 | for (module_id, _) in crate_def_map.modules.iter() { | 113 | for (module_id, _) in crate_def_map.modules() { |
114 | let file_id = crate_def_map[module_id].origin.file_id(); | 114 | let file_id = crate_def_map[module_id].origin.file_id(); |
115 | files.extend(file_id) | 115 | files.extend(file_id) |
116 | } | 116 | } |
@@ -135,7 +135,7 @@ impl TestDB { | |||
135 | let crate_def_map = self.crate_def_map(krate); | 135 | let crate_def_map = self.crate_def_map(krate); |
136 | 136 | ||
137 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); | 137 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
138 | for (module_id, module) in crate_def_map.modules.iter() { | 138 | for (module_id, module) in crate_def_map.modules() { |
139 | crate_def_map.add_diagnostics(self, module_id, &mut sink); | 139 | crate_def_map.add_diagnostics(self, module_id, &mut sink); |
140 | 140 | ||
141 | for decl in module.scope.declarations() { | 141 | for decl in module.scope.declarations() { |