aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs159
1 files changed, 106 insertions, 53 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f159f80af..c6bc85e2f 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -27,6 +27,7 @@ use crate::{
27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
28 }, 28 },
29 item_scope::BuiltinShadowMode, 29 item_scope::BuiltinShadowMode,
30 item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
30 path::{GenericArgs, Path}, 31 path::{GenericArgs, Path},
31 type_ref::{Mutability, Rawness, TypeRef}, 32 type_ref::{Mutability, Rawness, TypeRef},
32 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, 33 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
@@ -35,6 +36,8 @@ use crate::{
35 36
36use super::{ExprSource, PatSource}; 37use super::{ExprSource, PatSource};
37use ast::AstChildren; 38use ast::AstChildren;
39use rustc_hash::FxHashMap;
40use std::{any::type_name, sync::Arc};
38 41
39pub(crate) struct LowerCtx { 42pub(crate) struct LowerCtx {
40 hygiene: Hygiene, 43 hygiene: Hygiene,
@@ -60,10 +63,10 @@ pub(super) fn lower(
60 params: Option<ast::ParamList>, 63 params: Option<ast::ParamList>,
61 body: Option<ast::Expr>, 64 body: Option<ast::Expr>,
62) -> (Body, BodySourceMap) { 65) -> (Body, BodySourceMap) {
66 let item_tree = db.item_tree(expander.current_file_id);
63 ExprCollector { 67 ExprCollector {
64 db, 68 db,
65 def, 69 def,
66 expander,
67 source_map: BodySourceMap::default(), 70 source_map: BodySourceMap::default(),
68 body: Body { 71 body: Body {
69 exprs: Arena::default(), 72 exprs: Arena::default(),
@@ -72,6 +75,12 @@ pub(super) fn lower(
72 body_expr: dummy_expr_id(), 75 body_expr: dummy_expr_id(),
73 item_scope: Default::default(), 76 item_scope: Default::default(),
74 }, 77 },
78 item_trees: {
79 let mut map = FxHashMap::default();
80 map.insert(expander.current_file_id, item_tree);
81 map
82 },
83 expander,
75 } 84 }
76 .collect(params, body) 85 .collect(params, body)
77} 86}
@@ -82,6 +91,8 @@ struct ExprCollector<'a> {
82 expander: Expander, 91 expander: Expander,
83 body: Body, 92 body: Body,
84 source_map: BodySourceMap, 93 source_map: BodySourceMap,
94
95 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
85} 96}
86 97
87impl ExprCollector<'_> { 98impl ExprCollector<'_> {
@@ -165,6 +176,7 @@ impl ExprCollector<'_> {
165 if !self.expander.is_cfg_enabled(&expr) { 176 if !self.expander.is_cfg_enabled(&expr) {
166 return self.missing_expr(); 177 return self.missing_expr();
167 } 178 }
179
168 match expr { 180 match expr {
169 ast::Expr::IfExpr(e) => { 181 ast::Expr::IfExpr(e) => {
170 let then_branch = self.collect_block_opt(e.then_branch()); 182 let then_branch = self.collect_block_opt(e.then_branch());
@@ -207,8 +219,12 @@ impl ExprCollector<'_> {
207 let body = self.collect_block_opt(e.block_expr()); 219 let body = self.collect_block_opt(e.block_expr());
208 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) 220 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
209 } 221 }
222 ast::Effect::Unsafe(_) => {
223 let body = self.collect_block_opt(e.block_expr());
224 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
225 }
210 // FIXME: we need to record these effects somewhere... 226 // FIXME: we need to record these effects somewhere...
211 ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => { 227 ast::Effect::Async(_) | ast::Effect::Label(_) => {
212 self.collect_block_opt(e.block_expr()) 228 self.collect_block_opt(e.block_expr())
213 } 229 }
214 }, 230 },
@@ -434,7 +450,6 @@ impl ExprCollector<'_> {
434 Mutability::from_mutable(e.mut_token().is_some()) 450 Mutability::from_mutable(e.mut_token().is_some())
435 }; 451 };
436 let rawness = Rawness::from_raw(raw_tok); 452 let rawness = Rawness::from_raw(raw_tok);
437
438 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr) 453 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
439 } 454 }
440 ast::Expr::PrefixExpr(e) => { 455 ast::Expr::PrefixExpr(e) => {
@@ -533,6 +548,9 @@ impl ExprCollector<'_> {
533 self.source_map 548 self.source_map
534 .expansions 549 .expansions
535 .insert(macro_call, self.expander.current_file_id); 550 .insert(macro_call, self.expander.current_file_id);
551
552 let item_tree = self.db.item_tree(self.expander.current_file_id);
553 self.item_trees.insert(self.expander.current_file_id, item_tree);
536 let id = self.collect_expr(expansion); 554 let id = self.collect_expr(expansion);
537 self.expander.exit(self.db, mark); 555 self.expander.exit(self.db, mark);
538 id 556 id
@@ -547,6 +565,32 @@ impl ExprCollector<'_> {
547 } 565 }
548 } 566 }
549 567
568 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
569 let id = self.expander.ast_id(ast);
570 let tree = &self.item_trees[&id.file_id];
571
572 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
573
574 // Root file (non-macro).
575 let item_tree_id = tree
576 .all_inner_items()
577 .chain(tree.top_level_items().iter().copied())
578 .filter_map(|mod_item| mod_item.downcast::<N>())
579 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
580 .or_else(|| {
581 log::debug!(
582 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
583 type_name::<N>(),
584 id,
585 ast.syntax(),
586 ast.syntax(),
587 );
588 None
589 })?;
590
591 Some(ItemTreeId::new(id.file_id, item_tree_id))
592 }
593
550 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 594 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
551 if let Some(expr) = expr { 595 if let Some(expr) = expr {
552 self.collect_expr(expr) 596 self.collect_expr(expr)
@@ -578,56 +622,65 @@ impl ExprCollector<'_> {
578 622
579 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 623 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
580 let container = ContainerId::DefWithBodyId(self.def); 624 let container = ContainerId::DefWithBodyId(self.def);
581 for item in block.items() { 625
582 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 626 let items = block
583 ast::ModuleItem::FnDef(def) => { 627 .items()
584 let ast_id = self.expander.ast_id(&def); 628 .filter_map(|item| {
585 ( 629 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
586 FunctionLoc { container: container.into(), ast_id }.intern(self.db).into(), 630 ast::ModuleItem::FnDef(def) => {
587 def.name(), 631 let id = self.find_inner_item(&def)?;
588 ) 632 (
589 } 633 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
590 ast::ModuleItem::TypeAliasDef(def) => { 634 def.name(),
591 let ast_id = self.expander.ast_id(&def); 635 )
592 ( 636 }
593 TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into(), 637 ast::ModuleItem::TypeAliasDef(def) => {
594 def.name(), 638 let id = self.find_inner_item(&def)?;
595 ) 639 (
596 } 640 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
597 ast::ModuleItem::ConstDef(def) => { 641 def.name(),
598 let ast_id = self.expander.ast_id(&def); 642 )
599 ( 643 }
600 ConstLoc { container: container.into(), ast_id }.intern(self.db).into(), 644 ast::ModuleItem::ConstDef(def) => {
601 def.name(), 645 let id = self.find_inner_item(&def)?;
602 ) 646 (
603 } 647 ConstLoc { container: container.into(), id }.intern(self.db).into(),
604 ast::ModuleItem::StaticDef(def) => { 648 def.name(),
605 let ast_id = self.expander.ast_id(&def); 649 )
606 (StaticLoc { container, ast_id }.intern(self.db).into(), def.name()) 650 }
607 } 651 ast::ModuleItem::StaticDef(def) => {
608 ast::ModuleItem::StructDef(def) => { 652 let id = self.find_inner_item(&def)?;
609 let ast_id = self.expander.ast_id(&def); 653 (StaticLoc { container, id }.intern(self.db).into(), def.name())
610 (StructLoc { container, ast_id }.intern(self.db).into(), def.name()) 654 }
611 } 655 ast::ModuleItem::StructDef(def) => {
612 ast::ModuleItem::EnumDef(def) => { 656 let id = self.find_inner_item(&def)?;
613 let ast_id = self.expander.ast_id(&def); 657 (StructLoc { container, id }.intern(self.db).into(), def.name())
614 (EnumLoc { container, ast_id }.intern(self.db).into(), def.name()) 658 }
615 } 659 ast::ModuleItem::EnumDef(def) => {
616 ast::ModuleItem::UnionDef(def) => { 660 let id = self.find_inner_item(&def)?;
617 let ast_id = self.expander.ast_id(&def); 661 (EnumLoc { container, id }.intern(self.db).into(), def.name())
618 (UnionLoc { container, ast_id }.intern(self.db).into(), def.name()) 662 }
619 } 663 ast::ModuleItem::UnionDef(def) => {
620 ast::ModuleItem::TraitDef(def) => { 664 let id = self.find_inner_item(&def)?;
621 let ast_id = self.expander.ast_id(&def); 665 (UnionLoc { container, id }.intern(self.db).into(), def.name())
622 (TraitLoc { container, ast_id }.intern(self.db).into(), def.name()) 666 }
623 } 667 ast::ModuleItem::TraitDef(def) => {
624 ast::ModuleItem::ExternBlock(_) => continue, // FIXME: collect from extern blocks 668 let id = self.find_inner_item(&def)?;
625 ast::ModuleItem::ImplDef(_) 669 (TraitLoc { container, id }.intern(self.db).into(), def.name())
626 | ast::ModuleItem::UseItem(_) 670 }
627 | ast::ModuleItem::ExternCrateItem(_) 671 ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks
628 | ast::ModuleItem::Module(_) 672 ast::ModuleItem::ImplDef(_)
629 | ast::ModuleItem::MacroCall(_) => continue, 673 | ast::ModuleItem::UseItem(_)
630 }; 674 | ast::ModuleItem::ExternCrateItem(_)
675 | ast::ModuleItem::Module(_)
676 | ast::ModuleItem::MacroCall(_) => return None,
677 };
678
679 Some((def, name))
680 })
681 .collect::<Vec<_>>();
682
683 for (def, name) in items {
631 self.body.item_scope.define_def(def); 684 self.body.item_scope.define_def(def);
632 if let Some(name) = name { 685 if let Some(name) = name {
633 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 686 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly