aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/body/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/body/lower.rs')
-rw-r--r--crates/hir_def/src/body/lower.rs146
1 files changed, 7 insertions, 139 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index d4abe819d..4d79ab72c 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -1,13 +1,13 @@
1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` 1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation. 2//! representation.
3 3
4use std::{any::type_name, mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use either::Either; 6use either::Either;
7use hir_expand::{ 7use hir_expand::{
8 hygiene::Hygiene, 8 hygiene::Hygiene,
9 name::{name, AsName, Name}, 9 name::{name, AsName, Name},
10 ExpandError, HirFileId, MacroDefId, MacroDefKind, 10 ExpandError, HirFileId,
11}; 11};
12use la_arena::Arena; 12use la_arena::Arena;
13use profile::Count; 13use profile::Count;
@@ -32,11 +32,10 @@ use crate::{
32 Statement, 32 Statement,
33 }, 33 },
34 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
35 item_tree::{ItemTree, ItemTreeId, ItemTreeNode}, 35 item_tree::ItemTree,
36 path::{GenericArgs, Path}, 36 path::{GenericArgs, Path},
37 type_ref::{Mutability, Rawness, TypeRef}, 37 type_ref::{Mutability, Rawness, TypeRef},
38 AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, 38 AdtId, BlockLoc, ModuleDefId,
39 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
40}; 39};
41 40
42use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; 41use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
@@ -60,7 +59,6 @@ impl LowerCtx {
60 59
61pub(super) fn lower( 60pub(super) fn lower(
62 db: &dyn DefDatabase, 61 db: &dyn DefDatabase,
63 def: DefWithBodyId,
64 expander: Expander, 62 expander: Expander,
65 params: Option<ast::ParamList>, 63 params: Option<ast::ParamList>,
66 body: Option<ast::Expr>, 64 body: Option<ast::Expr>,
@@ -68,7 +66,6 @@ pub(super) fn lower(
68 let item_tree = db.item_tree(expander.current_file_id); 66 let item_tree = db.item_tree(expander.current_file_id);
69 ExprCollector { 67 ExprCollector {
70 db, 68 db,
71 def,
72 source_map: BodySourceMap::default(), 69 source_map: BodySourceMap::default(),
73 body: Body { 70 body: Body {
74 exprs: Arena::default(), 71 exprs: Arena::default(),
@@ -76,7 +73,7 @@ pub(super) fn lower(
76 labels: Arena::default(), 73 labels: Arena::default(),
77 params: Vec::new(), 74 params: Vec::new(),
78 body_expr: dummy_expr_id(), 75 body_expr: dummy_expr_id(),
79 item_scope: Default::default(), 76 block_scopes: Vec::new(),
80 _c: Count::new(), 77 _c: Count::new(),
81 }, 78 },
82 item_trees: { 79 item_trees: {
@@ -91,7 +88,6 @@ pub(super) fn lower(
91 88
92struct ExprCollector<'a> { 89struct ExprCollector<'a> {
93 db: &'a dyn DefDatabase, 90 db: &'a dyn DefDatabase,
94 def: DefWithBodyId,
95 expander: Expander, 91 expander: Expander,
96 body: Body, 92 body: Body,
97 source_map: BodySourceMap, 93 source_map: BodySourceMap,
@@ -605,32 +601,6 @@ impl ExprCollector<'_> {
605 } 601 }
606 } 602 }
607 603
608 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
609 let id = self.expander.ast_id(ast);
610 let tree = &self.item_trees[&id.file_id];
611
612 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
613
614 // Root file (non-macro).
615 let item_tree_id = tree
616 .all_inner_items()
617 .chain(tree.top_level_items().iter().copied())
618 .filter_map(|mod_item| mod_item.downcast::<N>())
619 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
620 .or_else(|| {
621 log::debug!(
622 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
623 type_name::<N>(),
624 id,
625 ast.syntax(),
626 ast.syntax(),
627 );
628 None
629 })?;
630
631 Some(ItemTreeId::new(id.file_id, item_tree_id))
632 }
633
634 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 604 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
635 if let Some(expr) = expr { 605 if let Some(expr) = expr {
636 self.collect_expr(expr) 606 self.collect_expr(expr)
@@ -662,7 +632,6 @@ impl ExprCollector<'_> {
662 match expansion { 632 match expansion {
663 Some(expansion) => { 633 Some(expansion) => {
664 let statements: ast::MacroStmts = expansion; 634 let statements: ast::MacroStmts = expansion;
665 this.collect_stmts_items(statements.statements());
666 635
667 statements.statements().for_each(|stmt| { 636 statements.statements().for_each(|stmt| {
668 if let Some(mut r) = this.collect_stmt(stmt) { 637 if let Some(mut r) = this.collect_stmt(stmt) {
@@ -700,6 +669,8 @@ impl ExprCollector<'_> {
700 let block_loc = 669 let block_loc =
701 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; 670 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
702 let block_id = self.db.intern_block(block_loc); 671 let block_id = self.db.intern_block(block_loc);
672 self.body.block_scopes.push(block_id);
673
703 let opt_def_map = self.db.block_def_map(block_id); 674 let opt_def_map = self.db.block_def_map(block_id);
704 let has_def_map = opt_def_map.is_some(); 675 let has_def_map = opt_def_map.is_some();
705 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); 676 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
@@ -707,7 +678,6 @@ impl ExprCollector<'_> {
707 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 678 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
708 let prev_local_module = mem::replace(&mut self.expander.module, module); 679 let prev_local_module = mem::replace(&mut self.expander.module, module);
709 680
710 self.collect_stmts_items(block.statements());
711 let statements = 681 let statements =
712 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); 682 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
713 let tail = block.tail_expr().map(|e| self.collect_expr(e)); 683 let tail = block.tail_expr().map(|e| self.collect_expr(e));
@@ -722,108 +692,6 @@ impl ExprCollector<'_> {
722 expr_id 692 expr_id
723 } 693 }
724 694
725 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
726 let container = ContainerId::DefWithBodyId(self.def);
727
728 let items = stmts
729 .filter_map(|stmt| match stmt {
730 ast::Stmt::Item(it) => Some(it),
731 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
732 })
733 .filter_map(|item| {
734 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
735 ast::Item::Fn(def) => {
736 let id = self.find_inner_item(&def)?;
737 (
738 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
739 def.name(),
740 )
741 }
742 ast::Item::TypeAlias(def) => {
743 let id = self.find_inner_item(&def)?;
744 (
745 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
746 def.name(),
747 )
748 }
749 ast::Item::Const(def) => {
750 let id = self.find_inner_item(&def)?;
751 (
752 ConstLoc { container: container.into(), id }.intern(self.db).into(),
753 def.name(),
754 )
755 }
756 ast::Item::Static(def) => {
757 let id = self.find_inner_item(&def)?;
758 (StaticLoc { container, id }.intern(self.db).into(), def.name())
759 }
760 ast::Item::Struct(def) => {
761 let id = self.find_inner_item(&def)?;
762 (StructLoc { container, id }.intern(self.db).into(), def.name())
763 }
764 ast::Item::Enum(def) => {
765 let id = self.find_inner_item(&def)?;
766 (EnumLoc { container, id }.intern(self.db).into(), def.name())
767 }
768 ast::Item::Union(def) => {
769 let id = self.find_inner_item(&def)?;
770 (UnionLoc { container, id }.intern(self.db).into(), def.name())
771 }
772 ast::Item::Trait(def) => {
773 let id = self.find_inner_item(&def)?;
774 (TraitLoc { container, id }.intern(self.db).into(), def.name())
775 }
776 ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
777 ast::Item::Impl(_)
778 | ast::Item::Use(_)
779 | ast::Item::ExternCrate(_)
780 | ast::Item::Module(_)
781 | ast::Item::MacroCall(_) => return None,
782 ast::Item::MacroRules(def) => {
783 return Some(Either::Right(ast::Macro::from(def)));
784 }
785 ast::Item::MacroDef(def) => {
786 return Some(Either::Right(ast::Macro::from(def)));
787 }
788 };
789
790 Some(Either::Left((def, name)))
791 })
792 .collect::<Vec<_>>();
793
794 for either in items {
795 match either {
796 Either::Left((def, name)) => {
797 self.body.item_scope.define_def(def);
798 if let Some(name) = name {
799 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
800 let has_constructor = match def {
801 ModuleDefId::AdtId(AdtId::StructId(s)) => {
802 self.db.struct_data(s).variant_data.kind() != StructKind::Record
803 }
804 _ => true,
805 };
806 self.body.item_scope.push_res(
807 name.as_name(),
808 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
809 );
810 }
811 }
812 Either::Right(e) => {
813 let mac = MacroDefId {
814 krate: self.expander.def_map.krate(),
815 ast_id: Some(self.expander.ast_id(&e)),
816 kind: MacroDefKind::Declarative,
817 local_inner: false,
818 };
819 if let Some(name) = e.name() {
820 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
821 }
822 }
823 }
824 }
825 }
826
827 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { 695 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
828 if let Some(block) = expr { 696 if let Some(block) = expr {
829 self.collect_block(block) 697 self.collect_block(block)