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.rs109
-rw-r--r--crates/hir_def/src/body/tests.rs2
2 files changed, 59 insertions, 52 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 19f5065d1..bfb75a8a5 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -30,6 +30,7 @@ use crate::{
30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, 30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
31 Statement, 31 Statement,
32 }, 32 },
33 intern::Interned,
33 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
34 path::{GenericArgs, Path}, 35 path::{GenericArgs, Path},
35 type_ref::{Mutability, Rawness, TypeRef}, 36 type_ref::{Mutability, Rawness, TypeRef},
@@ -74,6 +75,7 @@ pub(super) fn lower(
74 _c: Count::new(), 75 _c: Count::new(),
75 }, 76 },
76 expander, 77 expander,
78 statements_in_scope: Vec::new(),
77 } 79 }
78 .collect(params, body) 80 .collect(params, body)
79} 81}
@@ -83,6 +85,7 @@ struct ExprCollector<'a> {
83 expander: Expander, 85 expander: Expander,
84 body: Body, 86 body: Body,
85 source_map: BodySourceMap, 87 source_map: BodySourceMap,
88 statements_in_scope: Vec<Statement>,
86} 89}
87 90
88impl ExprCollector<'_> { 91impl ExprCollector<'_> {
@@ -320,8 +323,10 @@ impl ExprCollector<'_> {
320 Vec::new() 323 Vec::new()
321 }; 324 };
322 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
323 let generic_args = 326 let generic_args = e
324 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 327 .generic_arg_list()
328 .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
329 .map(Box::new);
325 self.alloc_expr( 330 self.alloc_expr(
326 Expr::MethodCall { receiver, method_name, args, generic_args }, 331 Expr::MethodCall { receiver, method_name, args, generic_args },
327 syntax_ptr, 332 syntax_ptr,
@@ -383,7 +388,7 @@ impl ExprCollector<'_> {
383 self.alloc_expr(Expr::Yield { expr }, syntax_ptr) 388 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
384 } 389 }
385 ast::Expr::RecordExpr(e) => { 390 ast::Expr::RecordExpr(e) => {
386 let path = e.path().and_then(|path| self.expander.parse_path(path)); 391 let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
387 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 392 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
388 let fields = nfl 393 let fields = nfl
389 .fields() 394 .fields()
@@ -428,7 +433,7 @@ impl ExprCollector<'_> {
428 } 433 }
429 ast::Expr::CastExpr(e) => { 434 ast::Expr::CastExpr(e) => {
430 let expr = self.collect_expr_opt(e.expr()); 435 let expr = self.collect_expr_opt(e.expr());
431 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); 436 let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
432 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 437 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
433 } 438 }
434 ast::Expr::RefExpr(e) => { 439 ast::Expr::RefExpr(e) => {
@@ -462,13 +467,16 @@ impl ExprCollector<'_> {
462 if let Some(pl) = e.param_list() { 467 if let Some(pl) = e.param_list() {
463 for param in pl.params() { 468 for param in pl.params() {
464 let pat = self.collect_pat_opt(param.pat()); 469 let pat = self.collect_pat_opt(param.pat());
465 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 470 let type_ref =
471 param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
466 args.push(pat); 472 args.push(pat);
467 arg_types.push(type_ref); 473 arg_types.push(type_ref);
468 } 474 }
469 } 475 }
470 let ret_type = 476 let ret_type = e
471 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); 477 .ret_type()
478 .and_then(|r| r.ty())
479 .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
472 let body = self.collect_expr_opt(e.body()); 480 let body = self.collect_expr_opt(e.body());
473 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 481 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
474 } 482 }
@@ -533,15 +541,13 @@ impl ExprCollector<'_> {
533 ids[0] 541 ids[0]
534 } 542 }
535 ast::Expr::MacroStmts(e) => { 543 ast::Expr::MacroStmts(e) => {
536 // FIXME: these statements should be held by some hir containter 544 e.statements().for_each(|s| self.collect_stmt(s));
537 for stmt in e.statements() { 545 let tail = e
538 self.collect_stmt(stmt); 546 .expr()
539 } 547 .map(|e| self.collect_expr(e))
540 if let Some(expr) = e.expr() { 548 .unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone()));
541 self.collect_expr(expr) 549
542 } else { 550 self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr)
543 self.alloc_expr(Expr::Missing, syntax_ptr)
544 }
545 } 551 }
546 }) 552 })
547 } 553 }
@@ -618,58 +624,55 @@ impl ExprCollector<'_> {
618 } 624 }
619 } 625 }
620 626
621 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { 627 fn collect_stmt(&mut self, s: ast::Stmt) {
622 let stmt = match s { 628 match s {
623 ast::Stmt::LetStmt(stmt) => { 629 ast::Stmt::LetStmt(stmt) => {
624 self.check_cfg(&stmt)?; 630 if self.check_cfg(&stmt).is_none() {
625 631 return;
632 }
626 let pat = self.collect_pat_opt(stmt.pat()); 633 let pat = self.collect_pat_opt(stmt.pat());
627 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 634 let type_ref =
635 stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
628 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 636 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
629 vec![Statement::Let { pat, type_ref, initializer }] 637 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
630 } 638 }
631 ast::Stmt::ExprStmt(stmt) => { 639 ast::Stmt::ExprStmt(stmt) => {
632 self.check_cfg(&stmt)?; 640 if self.check_cfg(&stmt).is_none() {
641 return;
642 }
633 643
634 // Note that macro could be expended to multiple statements 644 // Note that macro could be expended to multiple statements
635 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 645 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
636 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 646 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
637 let mut stmts = vec![];
638 647
639 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { 648 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
640 match expansion { 649 match expansion {
641 Some(expansion) => { 650 Some(expansion) => {
642 let statements: ast::MacroStmts = expansion; 651 let statements: ast::MacroStmts = expansion;
643 652
644 statements.statements().for_each(|stmt| { 653 statements.statements().for_each(|stmt| this.collect_stmt(stmt));
645 if let Some(mut r) = this.collect_stmt(stmt) {
646 stmts.append(&mut r);
647 }
648 });
649 if let Some(expr) = statements.expr() { 654 if let Some(expr) = statements.expr() {
650 stmts.push(Statement::Expr(this.collect_expr(expr))); 655 let expr = this.collect_expr(expr);
656 this.statements_in_scope.push(Statement::Expr(expr));
651 } 657 }
652 } 658 }
653 None => { 659 None => {
654 stmts.push(Statement::Expr( 660 let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
655 this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 661 this.statements_in_scope.push(Statement::Expr(expr));
656 ));
657 } 662 }
658 } 663 }
659 }); 664 });
660 stmts
661 } else { 665 } else {
662 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] 666 let expr = self.collect_expr_opt(stmt.expr());
667 self.statements_in_scope.push(Statement::Expr(expr));
663 } 668 }
664 } 669 }
665 ast::Stmt::Item(item) => { 670 ast::Stmt::Item(item) => {
666 self.check_cfg(&item)?; 671 if self.check_cfg(&item).is_none() {
667 672 return;
668 return None; 673 }
669 } 674 }
670 }; 675 }
671
672 Some(stmt)
673 } 676 }
674 677
675 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { 678 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
@@ -677,18 +680,22 @@ impl ExprCollector<'_> {
677 let block_loc = 680 let block_loc =
678 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; 681 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
679 let block_id = self.db.intern_block(block_loc); 682 let block_id = self.db.intern_block(block_loc);
680 self.body.block_scopes.push(block_id);
681 683
682 let opt_def_map = self.db.block_def_map(block_id); 684 let (module, def_map) = match self.db.block_def_map(block_id) {
683 let has_def_map = opt_def_map.is_some(); 685 Some(def_map) => {
684 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); 686 self.body.block_scopes.push(block_id);
685 let module = if has_def_map { def_map.root() } else { self.expander.module }; 687 (def_map.root(), def_map)
688 }
689 None => (self.expander.module, self.expander.def_map.clone()),
690 };
686 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 691 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
687 let prev_local_module = mem::replace(&mut self.expander.module, module); 692 let prev_local_module = mem::replace(&mut self.expander.module, module);
693 let prev_statements = std::mem::take(&mut self.statements_in_scope);
694
695 block.statements().for_each(|s| self.collect_stmt(s));
688 696
689 let statements =
690 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
691 let tail = block.tail_expr().map(|e| self.collect_expr(e)); 697 let tail = block.tail_expr().map(|e| self.collect_expr(e));
698 let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
692 let syntax_node_ptr = AstPtr::new(&block.into()); 699 let syntax_node_ptr = AstPtr::new(&block.into());
693 let expr_id = self.alloc_expr( 700 let expr_id = self.alloc_expr(
694 Expr::Block { id: block_id, statements, tail, label: None }, 701 Expr::Block { id: block_id, statements, tail, label: None },
@@ -755,7 +762,7 @@ impl ExprCollector<'_> {
755 } 762 }
756 } 763 }
757 ast::Pat::TupleStructPat(p) => { 764 ast::Pat::TupleStructPat(p) => {
758 let path = p.path().and_then(|path| self.expander.parse_path(path)); 765 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
759 let (args, ellipsis) = self.collect_tuple_pat(p.fields()); 766 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
760 Pat::TupleStruct { path, args, ellipsis } 767 Pat::TupleStruct { path, args, ellipsis }
761 } 768 }
@@ -765,7 +772,7 @@ impl ExprCollector<'_> {
765 Pat::Ref { pat, mutability } 772 Pat::Ref { pat, mutability }
766 } 773 }
767 ast::Pat::PathPat(p) => { 774 ast::Pat::PathPat(p) => {
768 let path = p.path().and_then(|path| self.expander.parse_path(path)); 775 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
769 path.map(Pat::Path).unwrap_or(Pat::Missing) 776 path.map(Pat::Path).unwrap_or(Pat::Missing)
770 } 777 }
771 ast::Pat::OrPat(p) => { 778 ast::Pat::OrPat(p) => {
@@ -779,7 +786,7 @@ impl ExprCollector<'_> {
779 } 786 }
780 ast::Pat::WildcardPat(_) => Pat::Wild, 787 ast::Pat::WildcardPat(_) => Pat::Wild,
781 ast::Pat::RecordPat(p) => { 788 ast::Pat::RecordPat(p) => {
782 let path = p.path().and_then(|path| self.expander.parse_path(path)); 789 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
783 let args: Vec<_> = p 790 let args: Vec<_> = p
784 .record_pat_field_list() 791 .record_pat_field_list()
785 .expect("every struct should have a field list") 792 .expect("every struct should have a field list")
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index faa133297..c1d3e998f 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -143,7 +143,7 @@ fn f() {
143 //^^^^^^^^^^^^^ could not convert tokens 143 //^^^^^^^^^^^^^ could not convert tokens
144 144
145 env!("OUT_DIR"); 145 env!("OUT_DIR");
146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix 146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
147 147
148 compile_error!("compile_error works"); 148 compile_error!("compile_error works");
149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works 149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works