diff options
author | Edwin Cheng <[email protected]> | 2021-03-25 19:52:35 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2021-03-25 20:21:15 +0000 |
commit | 8ce15b02dea7152953775904fd937cced2422bc6 (patch) | |
tree | 7ae4be1d4da3bd083fe0bec65f9ed4f5db8eb8c4 /crates/hir_def | |
parent | 59fdd7c84c5fdc16573f3cca4081d6735eaa9208 (diff) |
Fix recursive macro statement expansion
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 68 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 8 |
4 files changed, 37 insertions, 52 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 | ||
88 | impl ExprCollector<'_> { | 90 | impl 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 }, |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 24be93773..6c7376fad 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -171,6 +171,9 @@ pub enum Expr { | |||
171 | Unsafe { | 171 | Unsafe { |
172 | body: ExprId, | 172 | body: ExprId, |
173 | }, | 173 | }, |
174 | MacroStmts { | ||
175 | tail: ExprId, | ||
176 | }, | ||
174 | Array(Array), | 177 | Array(Array), |
175 | Literal(Literal), | 178 | Literal(Literal), |
176 | } | 179 | } |
@@ -357,6 +360,7 @@ impl Expr { | |||
357 | f(*repeat) | 360 | f(*repeat) |
358 | } | 361 | } |
359 | }, | 362 | }, |
363 | Expr::MacroStmts { tail } => f(*tail), | ||
360 | Expr::Literal(_) => {} | 364 | Expr::Literal(_) => {} |
361 | } | 365 | } |
362 | } | 366 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ae2475b4e..ca0048b16 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -110,15 +110,6 @@ impl ItemTree { | |||
110 | // still need to collect inner items. | 110 | // still need to collect inner items. |
111 | ctx.lower_inner_items(e.syntax()) | 111 | ctx.lower_inner_items(e.syntax()) |
112 | }, | 112 | }, |
113 | ast::ExprStmt(stmt) => { | ||
114 | // Macros can expand to stmt. We return an empty item tree in this case, but | ||
115 | // still need to collect inner items. | ||
116 | ctx.lower_inner_items(stmt.syntax()) | ||
117 | }, | ||
118 | ast::Item(item) => { | ||
119 | // Macros can expand to stmt and other item, and we add it as top level item | ||
120 | ctx.lower_single_item(item) | ||
121 | }, | ||
122 | _ => { | 113 | _ => { |
123 | panic!("cannot create item tree from {:?} {}", syntax, syntax); | 114 | panic!("cannot create item tree from {:?} {}", syntax, syntax); |
124 | }, | 115 | }, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index d3fe1ce1e..3f558edd8 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -87,14 +87,6 @@ impl Ctx { | |||
87 | self.tree | 87 | self.tree |
88 | } | 88 | } |
89 | 89 | ||
90 | pub(super) fn lower_single_item(mut self, item: ast::Item) -> ItemTree { | ||
91 | self.tree.top_level = self | ||
92 | .lower_mod_item(&item, false) | ||
93 | .map(|item| item.0) | ||
94 | .unwrap_or_else(|| Default::default()); | ||
95 | self.tree | ||
96 | } | ||
97 | |||
98 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { | 90 | pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree { |
99 | self.collect_inner_items(within); | 91 | self.collect_inner_items(within); |
100 | self.tree | 92 | self.tree |