diff options
Diffstat (limited to 'crates/hir_def/src/item_tree/lower.rs')
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5e71ca42c..8f2f0b340 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,19 +37,17 @@ 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 | ||
44 | impl Ctx { | 43 | impl Ctx { |
45 | 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 { |
46 | Self { | 45 | Self { |
47 | tree: ItemTree::empty(), | 46 | tree: ItemTree::default(), |
48 | hygiene, | 47 | hygiene, |
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 | } |
@@ -63,6 +61,32 @@ impl Ctx { | |||
63 | self.tree | 61 | self.tree |
64 | } | 62 | } |
65 | 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 | |||
66 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { | 90 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { |
67 | self.collect_inner_items(within); | 91 | self.collect_inner_items(within); |
68 | self.tree | 92 | self.tree |
@@ -73,8 +97,6 @@ impl Ctx { | |||
73 | } | 97 | } |
74 | 98 | ||
75 | fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { | 99 | 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. | 100 | // Collect inner items for 1-to-1-lowered items. |
79 | match item { | 101 | match item { |
80 | ast::Item::Struct(_) | 102 | ast::Item::Struct(_) |
@@ -150,14 +172,38 @@ impl Ctx { | |||
150 | 172 | ||
151 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 173 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
152 | let forced_vis = self.forced_visibility.take(); | 174 | let forced_vis = self.forced_visibility.take(); |
153 | let mut inner_items = mem::take(&mut self.tree.inner_items); | 175 | |
154 | inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( | 176 | let mut block_stack = Vec::new(); |
155 | |item| { | 177 | for event in container.preorder().skip(1) { |
156 | let ast_id = self.source_ast_id_map.ast_id(&item); | 178 | match event { |
157 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | 179 | WalkEvent::Enter(node) => { |
158 | }, | 180 | match_ast! { |
159 | )); | 181 | match node { |
160 | self.tree.inner_items = inner_items; | 182 | ast::BlockExpr(block) => { |
183 | block_stack.push(self.source_ast_id_map.ast_id(&block)); | ||
184 | }, | ||
185 | ast::Item(item) => { | ||
186 | // FIXME: This triggers for macro calls in expression position | ||
187 | let mod_items = self.lower_mod_item(&item, true); | ||
188 | let current_block = block_stack.last(); | ||
189 | if let (Some(mod_items), Some(block)) = (mod_items, current_block) { | ||
190 | if !mod_items.0.is_empty() { | ||
191 | self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied()); | ||
192 | } | ||
193 | } | ||
194 | }, | ||
195 | _ => {} | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | WalkEvent::Leave(node) => { | ||
200 | if ast::BlockExpr::cast(node).is_some() { | ||
201 | block_stack.pop(); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
161 | self.forced_visibility = forced_vis; | 207 | self.forced_visibility = forced_vis; |
162 | } | 208 | } |
163 | 209 | ||
@@ -318,6 +364,7 @@ impl Ctx { | |||
318 | params.push(type_ref); | 364 | params.push(type_ref); |
319 | } | 365 | } |
320 | } | 366 | } |
367 | let params = params.into_iter().map(|param| self.data().type_refs.intern(param)).collect(); | ||
321 | 368 | ||
322 | let mut is_varargs = false; | 369 | let mut is_varargs = false; |
323 | if let Some(params) = func.param_list() { | 370 | if let Some(params) = func.param_list() { |
@@ -339,6 +386,8 @@ impl Ctx { | |||
339 | ret_type | 386 | ret_type |
340 | }; | 387 | }; |
341 | 388 | ||
389 | let ret_type = self.data().type_refs.intern(ret_type); | ||
390 | |||
342 | let has_body = func.body().is_some(); | 391 | let has_body = func.body().is_some(); |
343 | 392 | ||
344 | let ast_id = self.source_ast_id_map.ast_id(func); | 393 | let ast_id = self.source_ast_id_map.ast_id(func); |
@@ -350,7 +399,7 @@ impl Ctx { | |||
350 | has_body, | 399 | has_body, |
351 | is_unsafe: func.unsafe_token().is_some(), | 400 | is_unsafe: func.unsafe_token().is_some(), |
352 | is_extern: false, | 401 | is_extern: false, |
353 | params: params.into_boxed_slice(), | 402 | params, |
354 | is_varargs, | 403 | is_varargs, |
355 | ret_type, | 404 | ret_type, |
356 | ast_id, | 405 | ast_id, |
@@ -611,6 +660,7 @@ impl Ctx { | |||
611 | generics.fill(&self.body_ctx, sm, node); | 660 | generics.fill(&self.body_ctx, sm, node); |
612 | // lower `impl Trait` in arguments | 661 | // lower `impl Trait` in arguments |
613 | for param in &*func.params { | 662 | for param in &*func.params { |
663 | let param = self.data().type_refs.lookup(*param); | ||
614 | generics.fill_implicit_impl_trait_args(param); | 664 | generics.fill_implicit_impl_trait_args(param); |
615 | } | 665 | } |
616 | } | 666 | } |
@@ -663,11 +713,15 @@ impl Ctx { | |||
663 | self.data().vis.alloc(vis) | 713 | self.data().vis.alloc(vis) |
664 | } | 714 | } |
665 | 715 | ||
666 | fn lower_type_ref(&self, type_ref: &ast::Type) -> TypeRef { | 716 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { |
667 | TypeRef::from_ast(&self.body_ctx, type_ref.clone()) | 717 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); |
718 | self.data().type_refs.intern(tyref) | ||
668 | } | 719 | } |
669 | fn lower_type_ref_opt(&self, type_ref: Option<ast::Type>) -> TypeRef { | 720 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { |
670 | type_ref.map(|ty| self.lower_type_ref(&ty)).unwrap_or(TypeRef::Error) | 721 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { |
722 | Some(it) => it, | ||
723 | None => self.data().type_refs.intern(TypeRef::Error), | ||
724 | } | ||
671 | } | 725 | } |
672 | 726 | ||
673 | /// Forces the visibility `vis` to be used for all items lowered during execution of `f`. | 727 | /// Forces the visibility `vis` to be used for all items lowered during execution of `f`. |
@@ -696,7 +750,8 @@ impl Ctx { | |||
696 | 750 | ||
697 | fn desugar_future_path(orig: TypeRef) -> Path { | 751 | fn desugar_future_path(orig: TypeRef) -> Path { |
698 | let path = path![core::future::Future]; | 752 | let path = path![core::future::Future]; |
699 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | 753 | let mut generic_args: Vec<_> = |
754 | std::iter::repeat(None).take(path.segments().len() - 1).collect(); | ||
700 | let mut last = GenericArgs::empty(); | 755 | let mut last = GenericArgs::empty(); |
701 | let binding = | 756 | let binding = |
702 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; | 757 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; |