aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/body
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r--crates/hir_def/src/body/lower.rs160
-rw-r--r--crates/hir_def/src/body/scope.rs4
-rw-r--r--crates/hir_def/src/body/tests.rs3
-rw-r--r--crates/hir_def/src/body/tests/block.rs10
4 files changed, 15 insertions, 162 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 40beb2f7a..8c8eb8007 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -1,17 +1,16 @@
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;
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;
14use rustc_hash::FxHashMap;
15use syntax::{ 14use syntax::{
16 ast::{ 15 ast::{
17 self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner, 16 self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner,
@@ -19,7 +18,6 @@ use syntax::{
19 }, 18 },
20 AstNode, AstPtr, SyntaxNodePtr, 19 AstNode, AstPtr, SyntaxNodePtr,
21}; 20};
22use test_utils::mark;
23 21
24use crate::{ 22use crate::{
25 adt::StructKind, 23 adt::StructKind,
@@ -33,11 +31,9 @@ use crate::{
33 Statement, 31 Statement,
34 }, 32 },
35 item_scope::BuiltinShadowMode, 33 item_scope::BuiltinShadowMode,
36 item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
37 path::{GenericArgs, Path}, 34 path::{GenericArgs, Path},
38 type_ref::{Mutability, Rawness, TypeRef}, 35 type_ref::{Mutability, Rawness, TypeRef},
39 AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, 36 AdtId, BlockLoc, ModuleDefId,
40 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
41}; 37};
42 38
43use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource}; 39use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
@@ -61,15 +57,12 @@ impl LowerCtx {
61 57
62pub(super) fn lower( 58pub(super) fn lower(
63 db: &dyn DefDatabase, 59 db: &dyn DefDatabase,
64 def: DefWithBodyId,
65 expander: Expander, 60 expander: Expander,
66 params: Option<ast::ParamList>, 61 params: Option<ast::ParamList>,
67 body: Option<ast::Expr>, 62 body: Option<ast::Expr>,
68) -> (Body, BodySourceMap) { 63) -> (Body, BodySourceMap) {
69 let item_tree = db.item_tree(expander.current_file_id);
70 ExprCollector { 64 ExprCollector {
71 db, 65 db,
72 def,
73 source_map: BodySourceMap::default(), 66 source_map: BodySourceMap::default(),
74 body: Body { 67 body: Body {
75 exprs: Arena::default(), 68 exprs: Arena::default(),
@@ -77,14 +70,9 @@ pub(super) fn lower(
77 labels: Arena::default(), 70 labels: Arena::default(),
78 params: Vec::new(), 71 params: Vec::new(),
79 body_expr: dummy_expr_id(), 72 body_expr: dummy_expr_id(),
80 item_scope: Default::default(), 73 block_scopes: Vec::new(),
81 _c: Count::new(), 74 _c: Count::new(),
82 }, 75 },
83 item_trees: {
84 let mut map = FxHashMap::default();
85 map.insert(expander.current_file_id, item_tree);
86 map
87 },
88 expander, 76 expander,
89 } 77 }
90 .collect(params, body) 78 .collect(params, body)
@@ -92,12 +80,9 @@ pub(super) fn lower(
92 80
93struct ExprCollector<'a> { 81struct ExprCollector<'a> {
94 db: &'a dyn DefDatabase, 82 db: &'a dyn DefDatabase,
95 def: DefWithBodyId,
96 expander: Expander, 83 expander: Expander,
97 body: Body, 84 body: Body,
98 source_map: BodySourceMap, 85 source_map: BodySourceMap,
99
100 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
101} 86}
102 87
103impl ExprCollector<'_> { 88impl ExprCollector<'_> {
@@ -286,7 +271,7 @@ impl ExprCollector<'_> {
286 None => self.collect_expr_opt(condition.expr()), 271 None => self.collect_expr_opt(condition.expr()),
287 // if let -- desugar to match 272 // if let -- desugar to match
288 Some(pat) => { 273 Some(pat) => {
289 mark::hit!(infer_resolve_while_let); 274 cov_mark::hit!(infer_resolve_while_let);
290 let pat = self.collect_pat(pat); 275 let pat = self.collect_pat(pat);
291 let match_expr = self.collect_expr_opt(condition.expr()); 276 let match_expr = self.collect_expr_opt(condition.expr());
292 let placeholder_pat = self.missing_pat(); 277 let placeholder_pat = self.missing_pat();
@@ -594,9 +579,6 @@ impl ExprCollector<'_> {
594 } else { 579 } else {
595 self.source_map.expansions.insert(macro_call, self.expander.current_file_id); 580 self.source_map.expansions.insert(macro_call, self.expander.current_file_id);
596 581
597 let item_tree = self.db.item_tree(self.expander.current_file_id);
598 self.item_trees.insert(self.expander.current_file_id, item_tree);
599
600 let id = collector(self, Some(expansion)); 582 let id = collector(self, Some(expansion));
601 self.expander.exit(self.db, mark); 583 self.expander.exit(self.db, mark);
602 id 584 id
@@ -606,32 +588,6 @@ impl ExprCollector<'_> {
606 } 588 }
607 } 589 }
608 590
609 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
610 let id = self.expander.ast_id(ast);
611 let tree = &self.item_trees[&id.file_id];
612
613 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
614
615 // Root file (non-macro).
616 let item_tree_id = tree
617 .all_inner_items()
618 .chain(tree.top_level_items().iter().copied())
619 .filter_map(|mod_item| mod_item.downcast::<N>())
620 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
621 .or_else(|| {
622 log::debug!(
623 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
624 type_name::<N>(),
625 id,
626 ast.syntax(),
627 ast.syntax(),
628 );
629 None
630 })?;
631
632 Some(ItemTreeId::new(id.file_id, item_tree_id))
633 }
634
635 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId { 591 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
636 if let Some(expr) = expr { 592 if let Some(expr) = expr {
637 self.collect_expr(expr) 593 self.collect_expr(expr)
@@ -663,7 +619,6 @@ impl ExprCollector<'_> {
663 match expansion { 619 match expansion {
664 Some(expansion) => { 620 Some(expansion) => {
665 let statements: ast::MacroStmts = expansion; 621 let statements: ast::MacroStmts = expansion;
666 this.collect_stmts_items(statements.statements());
667 622
668 statements.statements().for_each(|stmt| { 623 statements.statements().for_each(|stmt| {
669 if let Some(mut r) = this.collect_stmt(stmt) { 624 if let Some(mut r) = this.collect_stmt(stmt) {
@@ -701,6 +656,8 @@ impl ExprCollector<'_> {
701 let block_loc = 656 let block_loc =
702 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; 657 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
703 let block_id = self.db.intern_block(block_loc); 658 let block_id = self.db.intern_block(block_loc);
659 self.body.block_scopes.push(block_id);
660
704 let opt_def_map = self.db.block_def_map(block_id); 661 let opt_def_map = self.db.block_def_map(block_id);
705 let has_def_map = opt_def_map.is_some(); 662 let has_def_map = opt_def_map.is_some();
706 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); 663 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
@@ -708,7 +665,6 @@ impl ExprCollector<'_> {
708 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 665 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
709 let prev_local_module = mem::replace(&mut self.expander.module, module); 666 let prev_local_module = mem::replace(&mut self.expander.module, module);
710 667
711 self.collect_stmts_items(block.statements());
712 let statements = 668 let statements =
713 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect(); 669 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
714 let tail = block.tail_expr().map(|e| self.collect_expr(e)); 670 let tail = block.tail_expr().map(|e| self.collect_expr(e));
@@ -723,108 +679,6 @@ impl ExprCollector<'_> {
723 expr_id 679 expr_id
724 } 680 }
725 681
726 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
727 let container = ContainerId::DefWithBodyId(self.def);
728
729 let items = stmts
730 .filter_map(|stmt| match stmt {
731 ast::Stmt::Item(it) => Some(it),
732 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
733 })
734 .filter_map(|item| {
735 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
736 ast::Item::Fn(def) => {
737 let id = self.find_inner_item(&def)?;
738 (
739 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
740 def.name(),
741 )
742 }
743 ast::Item::TypeAlias(def) => {
744 let id = self.find_inner_item(&def)?;
745 (
746 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
747 def.name(),
748 )
749 }
750 ast::Item::Const(def) => {
751 let id = self.find_inner_item(&def)?;
752 (
753 ConstLoc { container: container.into(), id }.intern(self.db).into(),
754 def.name(),
755 )
756 }
757 ast::Item::Static(def) => {
758 let id = self.find_inner_item(&def)?;
759 (StaticLoc { container, id }.intern(self.db).into(), def.name())
760 }
761 ast::Item::Struct(def) => {
762 let id = self.find_inner_item(&def)?;
763 (StructLoc { container, id }.intern(self.db).into(), def.name())
764 }
765 ast::Item::Enum(def) => {
766 let id = self.find_inner_item(&def)?;
767 (EnumLoc { container, id }.intern(self.db).into(), def.name())
768 }
769 ast::Item::Union(def) => {
770 let id = self.find_inner_item(&def)?;
771 (UnionLoc { container, id }.intern(self.db).into(), def.name())
772 }
773 ast::Item::Trait(def) => {
774 let id = self.find_inner_item(&def)?;
775 (TraitLoc { container, id }.intern(self.db).into(), def.name())
776 }
777 ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
778 ast::Item::Impl(_)
779 | ast::Item::Use(_)
780 | ast::Item::ExternCrate(_)
781 | ast::Item::Module(_)
782 | ast::Item::MacroCall(_) => return None,
783 ast::Item::MacroRules(def) => {
784 return Some(Either::Right(ast::Macro::from(def)));
785 }
786 ast::Item::MacroDef(def) => {
787 return Some(Either::Right(ast::Macro::from(def)));
788 }
789 };
790
791 Some(Either::Left((def, name)))
792 })
793 .collect::<Vec<_>>();
794
795 for either in items {
796 match either {
797 Either::Left((def, name)) => {
798 self.body.item_scope.define_def(def);
799 if let Some(name) = name {
800 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
801 let has_constructor = match def {
802 ModuleDefId::AdtId(AdtId::StructId(s)) => {
803 self.db.struct_data(s).variant_data.kind() != StructKind::Record
804 }
805 _ => true,
806 };
807 self.body.item_scope.push_res(
808 name.as_name(),
809 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
810 );
811 }
812 }
813 Either::Right(e) => {
814 let mac = MacroDefId {
815 krate: self.expander.def_map.krate(),
816 ast_id: Some(self.expander.ast_id(&e)),
817 kind: MacroDefKind::Declarative,
818 local_inner: false,
819 };
820 if let Some(name) = e.name() {
821 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
822 }
823 }
824 }
825 }
826 }
827
828 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { 682 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
829 if let Some(block) = expr { 683 if let Some(block) = expr {
830 self.collect_block(block) 684 self.collect_block(block)
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs
index 210b4a617..1bbb54fc6 100644
--- a/crates/hir_def/src/body/scope.rs
+++ b/crates/hir_def/src/body/scope.rs
@@ -186,7 +186,7 @@ mod tests {
186 use base_db::{fixture::WithFixture, FileId, SourceDatabase}; 186 use base_db::{fixture::WithFixture, FileId, SourceDatabase};
187 use hir_expand::{name::AsName, InFile}; 187 use hir_expand::{name::AsName, InFile};
188 use syntax::{algo::find_node_at_offset, ast, AstNode}; 188 use syntax::{algo::find_node_at_offset, ast, AstNode};
189 use test_utils::{assert_eq_text, extract_offset, mark}; 189 use test_utils::{assert_eq_text, extract_offset};
190 190
191 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; 191 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
192 192
@@ -454,7 +454,7 @@ fn foo() {
454 454
455 #[test] 455 #[test]
456 fn while_let_desugaring() { 456 fn while_let_desugaring() {
457 mark::check!(infer_resolve_while_let); 457 cov_mark::check!(infer_resolve_while_let);
458 do_check_local_name( 458 do_check_local_name(
459 r#" 459 r#"
460fn test() { 460fn test() {
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index bb43569d7..991a32b15 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -2,7 +2,6 @@ mod block;
2 2
3use base_db::{fixture::WithFixture, SourceDatabase}; 3use base_db::{fixture::WithFixture, SourceDatabase};
4use expect_test::Expect; 4use expect_test::Expect;
5use test_utils::mark;
6 5
7use crate::{test_db::TestDB, ModuleDefId}; 6use crate::{test_db::TestDB, ModuleDefId};
8 7
@@ -48,7 +47,7 @@ fn check_at(ra_fixture: &str, expect: Expect) {
48 47
49#[test] 48#[test]
50fn your_stack_belongs_to_me() { 49fn your_stack_belongs_to_me() {
51 mark::check!(your_stack_belongs_to_me); 50 cov_mark::check!(your_stack_belongs_to_me);
52 lower( 51 lower(
53 " 52 "
54macro_rules! n_nuple { 53macro_rules! n_nuple {
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs
index 8bca72a17..3b6ba4cde 100644
--- a/crates/hir_def/src/body/tests/block.rs
+++ b/crates/hir_def/src/body/tests/block.rs
@@ -165,16 +165,16 @@ fn macro_resolve() {
165 check_at( 165 check_at(
166 r#" 166 r#"
167//- /lib.rs crate:lib deps:core 167//- /lib.rs crate:lib deps:core
168use core::mark; 168use core::cov_mark;
169 169
170fn f() { 170fn f() {
171 fn nested() { 171 fn nested() {
172 mark::hit!(Hit); 172 cov_mark::hit!(Hit);
173 $0 173 $0
174 } 174 }
175} 175}
176//- /core.rs crate:core 176//- /core.rs crate:core
177pub mod mark { 177pub mod cov_mark {
178 #[macro_export] 178 #[macro_export]
179 macro_rules! _hit { 179 macro_rules! _hit {
180 ($name:ident) => { 180 ($name:ident) => {
@@ -193,8 +193,8 @@ pub mod mark {
193 nested: v 193 nested: v
194 194
195 crate 195 crate
196 cov_mark: t
196 f: v 197 f: v
197 mark: t
198 "#]], 198 "#]],
199 ); 199 );
200} 200}
@@ -264,7 +264,7 @@ fn main() {
264fn underscore_import() { 264fn underscore_import() {
265 // This used to panic, because the default (private) visibility inside block expressions would 265 // This used to panic, because the default (private) visibility inside block expressions would
266 // point into the containing `DefMap`, which visibilities should never be able to do. 266 // point into the containing `DefMap`, which visibilities should never be able to do.
267 mark::check!(adjust_vis_in_block_def_map); 267 cov_mark::check!(adjust_vis_in_block_def_map);
268 check_at( 268 check_at(
269 r#" 269 r#"
270mod m { 270mod m {