aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/item_tree/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/item_tree/lower.rs')
-rw-r--r--crates/hir_def/src/item_tree/lower.rs95
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}
6use smallvec::SmallVec; 6use smallvec::SmallVec;
7use syntax::{ 7use syntax::{
8 ast::{self, ModuleItemOwner}, 8 ast::{self, ModuleItemOwner},
9 SyntaxNode, 9 SyntaxNode, WalkEvent,
10}; 10};
11 11
12use crate::{ 12use 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
44impl Ctx { 43impl 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
697fn desugar_future_path(orig: TypeRef) -> Path { 751fn 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() };