diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 10 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 26 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 13 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/block.rs | 63 |
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; | |||
48 | pub(super) fn collect_defs( | 48 | pub(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 ¤t_map.block { | 132 | match ¤t_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] | ||
126 | fn legacy_macro_items() { | ||
127 | // Checks that legacy-scoped `macro_rules!` from parent namespaces are resolved and expanded | ||
128 | // correctly. | ||
129 | check_at( | ||
130 | r#" | ||
131 | macro_rules! hit { | ||
132 | () => { | ||
133 | struct Hit {} | ||
134 | } | ||
135 | } | ||
136 | |||
137 | fn 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] | ||
152 | fn macro_resolve() { | ||
153 | check_at( | ||
154 | r#" | ||
155 | //- /lib.rs crate:lib deps:core | ||
156 | use core::mark; | ||
157 | |||
158 | fn f() { | ||
159 | fn nested() { | ||
160 | mark::hit!(Hit); | ||
161 | $0 | ||
162 | } | ||
163 | } | ||
164 | //- /core.rs crate:core | ||
165 | pub 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 | } | ||