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.rs105
1 files changed, 58 insertions, 47 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 08f0c32f4..60b25db56 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -519,7 +519,7 @@ impl ExprCollector<'_> {
519 } 519 }
520 ast::Expr::MacroCall(e) => { 520 ast::Expr::MacroCall(e) => {
521 let mut ids = vec![]; 521 let mut ids = vec![];
522 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| { 522 self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| {
523 ids.push(match expansion { 523 ids.push(match expansion {
524 Some(it) => this.collect_expr(it), 524 Some(it) => this.collect_expr(it),
525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -527,6 +527,17 @@ impl ExprCollector<'_> {
527 }); 527 });
528 ids[0] 528 ids[0]
529 } 529 }
530 ast::Expr::MacroStmts(e) => {
531 // FIXME: these statements should be held by some hir containter
532 for stmt in e.statements() {
533 self.collect_stmt(stmt);
534 }
535 if let Some(expr) = e.expr() {
536 self.collect_expr(expr)
537 } else {
538 self.alloc_expr(Expr::Missing, syntax_ptr)
539 }
540 }
530 } 541 }
531 } 542 }
532 543
@@ -534,6 +545,7 @@ impl ExprCollector<'_> {
534 &mut self, 545 &mut self,
535 e: ast::MacroCall, 546 e: ast::MacroCall,
536 syntax_ptr: AstPtr<ast::Expr>, 547 syntax_ptr: AstPtr<ast::Expr>,
548 is_error_recoverable: bool,
537 mut collector: F, 549 mut collector: F,
538 ) { 550 ) {
539 // File containing the macro call. Expansion errors will be attached here. 551 // File containing the macro call. Expansion errors will be attached here.
@@ -578,7 +590,7 @@ impl ExprCollector<'_> {
578 Some((mark, expansion)) => { 590 Some((mark, expansion)) => {
579 // FIXME: Statements are too complicated to recover from error for now. 591 // FIXME: Statements are too complicated to recover from error for now.
580 // It is because we don't have any hygiene for local variable expansion right now. 592 // It is because we don't have any hygiene for local variable expansion right now.
581 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { 593 if !is_error_recoverable && res.err.is_some() {
582 self.expander.exit(self.db, mark); 594 self.expander.exit(self.db, mark);
583 collector(self, None); 595 collector(self, None);
584 } else { 596 } else {
@@ -602,56 +614,55 @@ impl ExprCollector<'_> {
602 } 614 }
603 615
604 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { 616 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
605 let stmt = 617 let stmt = match s {
606 match s { 618 ast::Stmt::LetStmt(stmt) => {
607 ast::Stmt::LetStmt(stmt) => { 619 self.check_cfg(&stmt)?;
608 self.check_cfg(&stmt)?; 620
609 621 let pat = self.collect_pat_opt(stmt.pat());
610 let pat = self.collect_pat_opt(stmt.pat()); 622 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
611 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 623 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
612 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 624 vec![Statement::Let { pat, type_ref, initializer }]
613 vec![Statement::Let { pat, type_ref, initializer }] 625 }
614 } 626 ast::Stmt::ExprStmt(stmt) => {
615 ast::Stmt::ExprStmt(stmt) => { 627 self.check_cfg(&stmt)?;
616 self.check_cfg(&stmt)?; 628
617 629 // Note that macro could be expended to multiple statements
618 // Note that macro could be expended to multiple statements 630 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
619 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 631 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
620 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 632 let mut stmts = vec![];
621 let mut stmts = vec![]; 633
622 634 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
623 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| { 635 match expansion {
624 match expansion { 636 Some(expansion) => {
625 Some(expansion) => { 637 let statements: ast::MacroStmts = expansion;
626 let statements: ast::MacroStmts = expansion; 638
627 639 statements.statements().for_each(|stmt| {
628 statements.statements().for_each(|stmt| { 640 if let Some(mut r) = this.collect_stmt(stmt) {
629 if let Some(mut r) = this.collect_stmt(stmt) { 641 stmts.append(&mut r);
630 stmts.append(&mut r);
631 }
632 });
633 if let Some(expr) = statements.expr() {
634 stmts.push(Statement::Expr(this.collect_expr(expr)));
635 } 642 }
636 } 643 });
637 None => { 644 if let Some(expr) = statements.expr() {
638 stmts.push(Statement::Expr( 645 stmts.push(Statement::Expr(this.collect_expr(expr)));
639 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
640 ));
641 } 646 }
642 } 647 }
643 }); 648 None => {
644 stmts 649 stmts.push(Statement::Expr(
645 } else { 650 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
646 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] 651 ));
647 } 652 }
653 }
654 });
655 stmts
656 } else {
657 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
648 } 658 }
649 ast::Stmt::Item(item) => { 659 }
650 self.check_cfg(&item)?; 660 ast::Stmt::Item(item) => {
661 self.check_cfg(&item)?;
651 662
652 return None; 663 return None;
653 } 664 }
654 }; 665 };
655 666
656 Some(stmt) 667 Some(stmt)
657 } 668 }