diff options
Diffstat (limited to 'crates/hir_def/src/body')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 105 |
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 | } |