aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/item_tree.rs10
-rw-r--r--crates/hir_def/src/item_tree/lower.rs26
-rw-r--r--crates/hir_def/src/nameres.rs12
-rw-r--r--crates/hir_def/src/nameres/collector.rs13
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs7
-rw-r--r--crates/hir_def/src/nameres/tests/block.rs63
6 files changed, 109 insertions, 22 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 1e5c94660..42d9f0947 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -98,15 +98,17 @@ impl ItemTree {
98 ctx.lower_module_items(&items) 98 ctx.lower_module_items(&items)
99 }, 99 },
100 ast::MacroStmts(stmts) => { 100 ast::MacroStmts(stmts) => {
101 ctx.lower_inner_items(stmts.syntax()) 101 // The produced statements can include items, which should be added as top-level
102 // items.
103 ctx.lower_macro_stmts(stmts)
102 }, 104 },
103 // Macros can expand to expressions. We return an empty item tree in this case, but
104 // still need to collect inner items.
105 ast::Expr(e) => { 105 ast::Expr(e) => {
106 // Macros can expand to expressions. We return an empty item tree in this case, but
107 // still need to collect inner items.
106 ctx.lower_inner_items(e.syntax()) 108 ctx.lower_inner_items(e.syntax())
107 }, 109 },
108 _ => { 110 _ => {
109 panic!("cannot create item tree from {:?}", syntax); 111 panic!("cannot create item tree from {:?} {}", syntax, syntax);
110 }, 112 },
111 } 113 }
112 }; 114 };
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 8a71376b9..acc001add 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -61,6 +61,32 @@ impl Ctx {
61 self.tree 61 self.tree
62 } 62 }
63 63
64 pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree {
65 self.tree.top_level = stmts
66 .statements()
67 .filter_map(|stmt| match stmt {
68 ast::Stmt::Item(item) => Some(item),
69 _ => None,
70 })
71 .flat_map(|item| self.lower_mod_item(&item, false))
72 .flat_map(|items| items.0)
73 .collect();
74
75 // Non-items need to have their inner items collected.
76 for stmt in stmts.statements() {
77 match stmt {
78 ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => {
79 self.collect_inner_items(stmt.syntax())
80 }
81 _ => {}
82 }
83 }
84 if let Some(expr) = stmts.expr() {
85 self.collect_inner_items(expr.syntax());
86 }
87 self.tree
88 }
89
64 pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { 90 pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree {
65 self.collect_inner_items(within); 91 self.collect_inner_items(within);
66 self.tree 92 self.tree
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 005b36e02..6169b3bbc 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -199,16 +199,10 @@ impl DefMap {
199 199
200 pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> { 200 pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
201 let block: BlockLoc = db.lookup_intern_block(block_id); 201 let block: BlockLoc = db.lookup_intern_block(block_id);
202 let item_tree = db.item_tree(block.ast_id.file_id);
203 let block_items = item_tree.inner_items_of_block(block.ast_id.value);
204
205 let parent = block.module.def_map(db); 202 let parent = block.module.def_map(db);
206 203
207 if block_items.is_empty() { 204 // FIXME: It would be good to just return the parent map when the block has no items, but
208 // If there are no inner items, nothing new is brought into scope, so we can just return 205 // we rely on `def_map.block` in a few places, which is `Some` for the inner `DefMap`.
209 // the parent DefMap. This keeps DefMap parent chains short.
210 return parent;
211 }
212 206
213 let block_info = 207 let block_info =
214 BlockInfo { block: block_id, parent, parent_module: block.module.local_id }; 208 BlockInfo { block: block_id, parent, parent_module: block.module.local_id };
@@ -216,7 +210,7 @@ impl DefMap {
216 let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition); 210 let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition);
217 def_map.block = Some(block_info); 211 def_map.block = Some(block_info);
218 212
219 let def_map = collector::collect_defs(db, def_map, Some(block.ast_id.value)); 213 let def_map = collector::collect_defs(db, def_map, Some(block.ast_id));
220 Arc::new(def_map) 214 Arc::new(def_map)
221 } 215 }
222 216
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 761b29c86..ae98fadac 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -48,7 +48,7 @@ const FIXED_POINT_LIMIT: usize = 8192;
48pub(super) fn collect_defs( 48pub(super) fn collect_defs(
49 db: &dyn DefDatabase, 49 db: &dyn DefDatabase,
50 mut def_map: DefMap, 50 mut def_map: DefMap,
51 block: Option<FileAstId<ast::BlockExpr>>, 51 block: Option<AstId<ast::BlockExpr>>,
52) -> DefMap { 52) -> DefMap {
53 let crate_graph = db.crate_graph(); 53 let crate_graph = db.crate_graph();
54 54
@@ -261,11 +261,10 @@ impl DefCollector<'_> {
261 } 261 }
262 } 262 }
263 263
264 fn seed_with_inner(&mut self, block: FileAstId<ast::BlockExpr>) { 264 fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) {
265 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; 265 let item_tree = self.db.item_tree(block.file_id);
266 let item_tree = self.db.item_tree(file_id.into());
267 let module_id = self.def_map.root; 266 let module_id = self.def_map.root;
268 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; 267 self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block };
269 if item_tree 268 if item_tree
270 .top_level_attrs(self.db, self.def_map.krate) 269 .top_level_attrs(self.db, self.def_map.krate)
271 .cfg() 270 .cfg()
@@ -275,11 +274,11 @@ impl DefCollector<'_> {
275 def_collector: &mut *self, 274 def_collector: &mut *self,
276 macro_depth: 0, 275 macro_depth: 0,
277 module_id, 276 module_id,
278 file_id: file_id.into(), 277 file_id: block.file_id,
279 item_tree: &item_tree, 278 item_tree: &item_tree,
280 mod_dir: ModDir::root(), 279 mod_dir: ModDir::root(),
281 } 280 }
282 .collect(item_tree.inner_items_of_block(block)); 281 .collect(item_tree.inner_items_of_block(block.value));
283 } 282 }
284 } 283 }
285 284
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 419e465ed..2a0f8ec2b 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -103,7 +103,7 @@ impl DefMap {
103 &self, 103 &self,
104 db: &dyn DefDatabase, 104 db: &dyn DefDatabase,
105 mode: ResolveMode, 105 mode: ResolveMode,
106 original_module: LocalModuleId, 106 mut original_module: LocalModuleId,
107 path: &ModPath, 107 path: &ModPath,
108 shadow: BuiltinShadowMode, 108 shadow: BuiltinShadowMode,
109 ) -> ResolvePathResult { 109 ) -> ResolvePathResult {
@@ -130,7 +130,10 @@ impl DefMap {
130 result.segment_index = result.segment_index.min(new.segment_index); 130 result.segment_index = result.segment_index.min(new.segment_index);
131 131
132 match &current_map.block { 132 match &current_map.block {
133 Some(block) => current_map = &block.parent, 133 Some(block) => {
134 current_map = &block.parent;
135 original_module = block.parent_module;
136 }
134 None => return result, 137 None => return result,
135 } 138 }
136 } 139 }
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs
index 470ca593e..6cc659513 100644
--- a/crates/hir_def/src/nameres/tests/block.rs
+++ b/crates/hir_def/src/nameres/tests/block.rs
@@ -121,3 +121,66 @@ struct Struct {}
121 "#]], 121 "#]],
122 ); 122 );
123} 123}
124
125#[test]
126fn legacy_macro_items() {
127 // Checks that legacy-scoped `macro_rules!` from parent namespaces are resolved and expanded
128 // correctly.
129 check_at(
130 r#"
131macro_rules! hit {
132 () => {
133 struct Hit {}
134 }
135}
136
137fn f() {
138 hit!();
139 $0
140}
141"#,
142 expect![[r#"
143 block scope
144 Hit: t
145 crate
146 f: v
147 "#]],
148 );
149}
150
151#[test]
152fn macro_resolve() {
153 check_at(
154 r#"
155//- /lib.rs crate:lib deps:core
156use core::mark;
157
158fn f() {
159 fn nested() {
160 mark::hit!(Hit);
161 $0
162 }
163}
164//- /core.rs crate:core
165pub mod mark {
166 #[macro_export]
167 macro_rules! _hit {
168 ($name:ident) => {
169 struct $name {}
170 }
171 }
172
173 pub use crate::_hit as hit;
174}
175"#,
176 expect![[r#"
177 block scope
178 Hit: t
179 block scope
180 nested: v
181 crate
182 f: v
183 mark: t
184 "#]],
185 );
186}