aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/body
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-27 02:57:02 +0000
committerGitHub <[email protected]>2021-03-27 02:57:02 +0000
commitc8066ebd1781a6f6f536abe3494477bd69df795a (patch)
treeedf5109d9f0629b0910f4f2ac716bd624330bb00 /crates/hir_def/src/body
parent9c9376c4cffdd171375fbb21dd3d0f71a97a335e (diff)
parent8ce15b02dea7152953775904fd937cced2422bc6 (diff)
Merge #8201
8201: Fix recursive macro statements expansion r=edwin0cheng a=edwin0cheng This PR attempts to properly handle macro statement expansion by implementing the following: 1. Merge macro expanded statements to parent scope statements. 2. Add a new hir `Expr::MacroStmts` for handle tail expression infer. PS : The scope of macro expanded statements are so strange that it took more time than I thought to understand and implement it :( Fixes #8171 Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r--crates/hir_def/src/body/lower.rs68
1 files changed, 33 insertions, 35 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 19f5065d1..229e81dd4 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -74,6 +74,7 @@ pub(super) fn lower(
74 _c: Count::new(), 74 _c: Count::new(),
75 }, 75 },
76 expander, 76 expander,
77 statements_in_scope: Vec::new(),
77 } 78 }
78 .collect(params, body) 79 .collect(params, body)
79} 80}
@@ -83,6 +84,7 @@ struct ExprCollector<'a> {
83 expander: Expander, 84 expander: Expander,
84 body: Body, 85 body: Body,
85 source_map: BodySourceMap, 86 source_map: BodySourceMap,
87 statements_in_scope: Vec<Statement>,
86} 88}
87 89
88impl ExprCollector<'_> { 90impl ExprCollector<'_> {
@@ -533,15 +535,13 @@ impl ExprCollector<'_> {
533 ids[0] 535 ids[0]
534 } 536 }
535 ast::Expr::MacroStmts(e) => { 537 ast::Expr::MacroStmts(e) => {
536 // FIXME: these statements should be held by some hir containter 538 e.statements().for_each(|s| self.collect_stmt(s));
537 for stmt in e.statements() { 539 let tail = e
538 self.collect_stmt(stmt); 540 .expr()
539 } 541 .map(|e| self.collect_expr(e))
540 if let Some(expr) = e.expr() { 542 .unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone()));
541 self.collect_expr(expr) 543
542 } else { 544 self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr)
543 self.alloc_expr(Expr::Missing, syntax_ptr)
544 }
545 } 545 }
546 }) 546 })
547 } 547 }
@@ -618,58 +618,54 @@ impl ExprCollector<'_> {
618 } 618 }
619 } 619 }
620 620
621 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { 621 fn collect_stmt(&mut self, s: ast::Stmt) {
622 let stmt = match s { 622 match s {
623 ast::Stmt::LetStmt(stmt) => { 623 ast::Stmt::LetStmt(stmt) => {
624 self.check_cfg(&stmt)?; 624 if self.check_cfg(&stmt).is_none() {
625 625 return;
626 }
626 let pat = self.collect_pat_opt(stmt.pat()); 627 let pat = self.collect_pat_opt(stmt.pat());
627 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 628 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
628 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 629 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
629 vec![Statement::Let { pat, type_ref, initializer }] 630 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
630 } 631 }
631 ast::Stmt::ExprStmt(stmt) => { 632 ast::Stmt::ExprStmt(stmt) => {
632 self.check_cfg(&stmt)?; 633 if self.check_cfg(&stmt).is_none() {
634 return;
635 }
633 636
634 // Note that macro could be expended to multiple statements 637 // Note that macro could be expended to multiple statements
635 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 638 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
636 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 639 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
637 let mut stmts = vec![];
638 640
639 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { 641 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
640 match expansion { 642 match expansion {
641 Some(expansion) => { 643 Some(expansion) => {
642 let statements: ast::MacroStmts = expansion; 644 let statements: ast::MacroStmts = expansion;
643 645
644 statements.statements().for_each(|stmt| { 646 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() { 647 if let Some(expr) = statements.expr() {
650 stmts.push(Statement::Expr(this.collect_expr(expr))); 648 let expr = this.collect_expr(expr);
649 this.statements_in_scope.push(Statement::Expr(expr));
651 } 650 }
652 } 651 }
653 None => { 652 None => {
654 stmts.push(Statement::Expr( 653 let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
655 this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 654 this.statements_in_scope.push(Statement::Expr(expr));
656 ));
657 } 655 }
658 } 656 }
659 }); 657 });
660 stmts
661 } else { 658 } else {
662 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] 659 let expr = self.collect_expr_opt(stmt.expr());
660 self.statements_in_scope.push(Statement::Expr(expr));
663 } 661 }
664 } 662 }
665 ast::Stmt::Item(item) => { 663 ast::Stmt::Item(item) => {
666 self.check_cfg(&item)?; 664 if self.check_cfg(&item).is_none() {
667 665 return;
668 return None; 666 }
669 } 667 }
670 }; 668 }
671
672 Some(stmt)
673 } 669 }
674 670
675 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { 671 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
@@ -685,10 +681,12 @@ impl ExprCollector<'_> {
685 let module = if has_def_map { def_map.root() } else { self.expander.module }; 681 let module = if has_def_map { def_map.root() } else { self.expander.module };
686 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 682 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); 683 let prev_local_module = mem::replace(&mut self.expander.module, module);
684 let prev_statements = std::mem::take(&mut self.statements_in_scope);
685
686 block.statements().for_each(|s| self.collect_stmt(s));
688 687
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)); 688 let tail = block.tail_expr().map(|e| self.collect_expr(e));
689 let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
692 let syntax_node_ptr = AstPtr::new(&block.into()); 690 let syntax_node_ptr = AstPtr::new(&block.into());
693 let expr_id = self.alloc_expr( 691 let expr_id = self.alloc_expr(
694 Expr::Block { id: block_id, statements, tail, label: None }, 692 Expr::Block { id: block_id, statements, tail, label: None },