diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 105 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 5 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 16 | ||||
-rw-r--r-- | crates/mbe/src/tests.rs | 11 | ||||
-rw-r--r-- | crates/parser/src/grammar.rs | 6 | ||||
-rw-r--r-- | crates/parser/src/grammar/expressions.rs | 6 | ||||
-rw-r--r-- | crates/syntax/src/ast/generated/nodes.rs | 10 |
8 files changed, 100 insertions, 62 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 8934ae6c9..7052058f2 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. |
@@ -567,7 +579,7 @@ impl ExprCollector<'_> { | |||
567 | Some((mark, expansion)) => { | 579 | Some((mark, expansion)) => { |
568 | // FIXME: Statements are too complicated to recover from error for now. | 580 | // FIXME: Statements are too complicated to recover from error for now. |
569 | // It is because we don't have any hygiene for local variable expansion right now. | 581 | // It is because we don't have any hygiene for local variable expansion right now. |
570 | if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { | 582 | if !is_error_recoverable && res.err.is_some() { |
571 | self.expander.exit(self.db, mark); | 583 | self.expander.exit(self.db, mark); |
572 | collector(self, None); | 584 | collector(self, None); |
573 | } else { | 585 | } else { |
@@ -591,56 +603,55 @@ impl ExprCollector<'_> { | |||
591 | } | 603 | } |
592 | 604 | ||
593 | fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { | 605 | fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { |
594 | let stmt = | 606 | let stmt = match s { |
595 | match s { | 607 | ast::Stmt::LetStmt(stmt) => { |
596 | ast::Stmt::LetStmt(stmt) => { | 608 | self.check_cfg(&stmt)?; |
597 | self.check_cfg(&stmt)?; | 609 | |
598 | 610 | let pat = self.collect_pat_opt(stmt.pat()); | |
599 | let pat = self.collect_pat_opt(stmt.pat()); | 611 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); |
600 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 612 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
601 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 613 | vec![Statement::Let { pat, type_ref, initializer }] |
602 | vec![Statement::Let { pat, type_ref, initializer }] | 614 | } |
603 | } | 615 | ast::Stmt::ExprStmt(stmt) => { |
604 | ast::Stmt::ExprStmt(stmt) => { | 616 | self.check_cfg(&stmt)?; |
605 | self.check_cfg(&stmt)?; | 617 | |
606 | 618 | // Note that macro could be expended to multiple statements | |
607 | // Note that macro could be expended to multiple statements | 619 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
608 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 620 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); |
609 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); | 621 | let mut stmts = vec![]; |
610 | let mut stmts = vec![]; | 622 | |
611 | 623 | self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { | |
612 | self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| { | 624 | match expansion { |
613 | match expansion { | 625 | Some(expansion) => { |
614 | Some(expansion) => { | 626 | let statements: ast::MacroStmts = expansion; |
615 | let statements: ast::MacroStmts = expansion; | 627 | |
616 | 628 | statements.statements().for_each(|stmt| { | |
617 | statements.statements().for_each(|stmt| { | 629 | if let Some(mut r) = this.collect_stmt(stmt) { |
618 | if let Some(mut r) = this.collect_stmt(stmt) { | 630 | stmts.append(&mut r); |
619 | stmts.append(&mut r); | ||
620 | } | ||
621 | }); | ||
622 | if let Some(expr) = statements.expr() { | ||
623 | stmts.push(Statement::Expr(this.collect_expr(expr))); | ||
624 | } | 631 | } |
625 | } | 632 | }); |
626 | None => { | 633 | if let Some(expr) = statements.expr() { |
627 | stmts.push(Statement::Expr( | 634 | stmts.push(Statement::Expr(this.collect_expr(expr))); |
628 | this.alloc_expr(Expr::Missing, syntax_ptr.clone()), | ||
629 | )); | ||
630 | } | 635 | } |
631 | } | 636 | } |
632 | }); | 637 | None => { |
633 | stmts | 638 | stmts.push(Statement::Expr( |
634 | } else { | 639 | this.alloc_expr(Expr::Missing, syntax_ptr.clone()), |
635 | vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] | 640 | )); |
636 | } | 641 | } |
642 | } | ||
643 | }); | ||
644 | stmts | ||
645 | } else { | ||
646 | vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] | ||
637 | } | 647 | } |
638 | ast::Stmt::Item(item) => { | 648 | } |
639 | self.check_cfg(&item)?; | 649 | ast::Stmt::Item(item) => { |
650 | self.check_cfg(&item)?; | ||
640 | 651 | ||
641 | return None; | 652 | return None; |
642 | } | 653 | } |
643 | }; | 654 | }; |
644 | 655 | ||
645 | Some(stmt) | 656 | Some(stmt) |
646 | } | 657 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 09bcb10dc..86239d903 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -110,6 +110,11 @@ 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 | }, | ||
113 | _ => { | 118 | _ => { |
114 | panic!("cannot create item tree from {:?} {}", syntax, syntax); | 119 | panic!("cannot create item tree from {:?} {}", syntax, syntax); |
115 | }, | 120 | }, |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 9086e6c17..a3070f1f9 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -401,13 +401,14 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | |||
401 | 401 | ||
402 | match parent.kind() { | 402 | match parent.kind() { |
403 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, | 403 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, |
404 | MACRO_STMTS => FragmentKind::Statement, | ||
404 | ITEM_LIST => FragmentKind::Items, | 405 | ITEM_LIST => FragmentKind::Items, |
405 | LET_STMT => { | 406 | LET_STMT => { |
406 | // FIXME: Handle Pattern | 407 | // FIXME: Handle Pattern |
407 | FragmentKind::Expr | 408 | FragmentKind::Expr |
408 | } | 409 | } |
409 | EXPR_STMT => FragmentKind::Statements, | 410 | EXPR_STMT => FragmentKind::Statements, |
410 | BLOCK_EXPR => FragmentKind::Expr, | 411 | BLOCK_EXPR => FragmentKind::Statements, |
411 | ARG_LIST => FragmentKind::Expr, | 412 | ARG_LIST => FragmentKind::Expr, |
412 | TRY_EXPR => FragmentKind::Expr, | 413 | TRY_EXPR => FragmentKind::Expr, |
413 | TUPLE_EXPR => FragmentKind::Expr, | 414 | TUPLE_EXPR => FragmentKind::Expr, |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index fb3afaedc..af4f8bb11 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -216,6 +216,22 @@ fn expr_macro_expanded_in_various_places() { | |||
216 | } | 216 | } |
217 | 217 | ||
218 | #[test] | 218 | #[test] |
219 | fn expr_macro_expanded_in_stmts() { | ||
220 | check_infer( | ||
221 | r#" | ||
222 | macro_rules! id { ($($es:tt)*) => { $($es)* } } | ||
223 | fn foo() { | ||
224 | id! { let a = (); } | ||
225 | } | ||
226 | "#, | ||
227 | expect![[r#" | ||
228 | !0..8 'leta=();': () | ||
229 | 57..84 '{ ...); } }': () | ||
230 | "#]], | ||
231 | ); | ||
232 | } | ||
233 | |||
234 | #[test] | ||
219 | fn infer_type_value_macro_having_same_name() { | 235 | fn infer_type_value_macro_having_same_name() { |
220 | check_infer( | 236 | check_infer( |
221 | r#" | 237 | r#" |
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 3a168bb4b..eca0bcc18 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs | |||
@@ -662,12 +662,11 @@ fn test_tt_to_stmts() { | |||
662 | [email protected] | 662 | [email protected] |
663 | [email protected] "1" | 663 | [email protected] "1" |
664 | [email protected] ";" | 664 | [email protected] ";" |
665 | [email protected] | 665 | [email protected] |
666 | [email protected] | 666 | [email protected] |
667 | [email protected] | 667 | [email protected] |
668 | [email protected] | 668 | [email protected] |
669 | [email protected] | 669 | [email protected] "a""#, |
670 | [email protected] "a""#, | ||
671 | ); | 670 | ); |
672 | } | 671 | } |
673 | 672 | ||
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 6c0e22722..cebb8f400 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs | |||
@@ -63,11 +63,11 @@ pub(crate) mod fragments { | |||
63 | } | 63 | } |
64 | 64 | ||
65 | pub(crate) fn stmt(p: &mut Parser) { | 65 | pub(crate) fn stmt(p: &mut Parser) { |
66 | expressions::stmt(p, expressions::StmtWithSemi::No) | 66 | expressions::stmt(p, expressions::StmtWithSemi::No, true) |
67 | } | 67 | } |
68 | 68 | ||
69 | pub(crate) fn stmt_optional_semi(p: &mut Parser) { | 69 | pub(crate) fn stmt_optional_semi(p: &mut Parser) { |
70 | expressions::stmt(p, expressions::StmtWithSemi::Optional) | 70 | expressions::stmt(p, expressions::StmtWithSemi::Optional, false) |
71 | } | 71 | } |
72 | 72 | ||
73 | pub(crate) fn opt_visibility(p: &mut Parser) { | 73 | pub(crate) fn opt_visibility(p: &mut Parser) { |
@@ -133,7 +133,7 @@ pub(crate) mod fragments { | |||
133 | continue; | 133 | continue; |
134 | } | 134 | } |
135 | 135 | ||
136 | expressions::stmt(p, expressions::StmtWithSemi::Optional); | 136 | expressions::stmt(p, expressions::StmtWithSemi::Optional, true); |
137 | } | 137 | } |
138 | 138 | ||
139 | m.complete(p, MACRO_STMTS); | 139 | m.complete(p, MACRO_STMTS); |
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs index 5f885edfd..0d9dc9348 100644 --- a/crates/parser/src/grammar/expressions.rs +++ b/crates/parser/src/grammar/expressions.rs | |||
@@ -54,7 +54,7 @@ fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { | |||
54 | !forbid | 54 | !forbid |
55 | } | 55 | } |
56 | 56 | ||
57 | pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | 57 | pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi, prefer_expr: bool) { |
58 | let m = p.start(); | 58 | let m = p.start(); |
59 | // test attr_on_expr_stmt | 59 | // test attr_on_expr_stmt |
60 | // fn foo() { | 60 | // fn foo() { |
@@ -90,7 +90,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
90 | p.error(format!("attributes are not allowed on {:?}", kind)); | 90 | p.error(format!("attributes are not allowed on {:?}", kind)); |
91 | } | 91 | } |
92 | 92 | ||
93 | if p.at(T!['}']) { | 93 | if p.at(T!['}']) || (prefer_expr && p.at(EOF)) { |
94 | // test attr_on_last_expr_in_block | 94 | // test attr_on_last_expr_in_block |
95 | // fn foo() { | 95 | // fn foo() { |
96 | // { #[A] bar!()? } | 96 | // { #[A] bar!()? } |
@@ -198,7 +198,7 @@ pub(super) fn expr_block_contents(p: &mut Parser) { | |||
198 | continue; | 198 | continue; |
199 | } | 199 | } |
200 | 200 | ||
201 | stmt(p, StmtWithSemi::Yes) | 201 | stmt(p, StmtWithSemi::Yes, false) |
202 | } | 202 | } |
203 | } | 203 | } |
204 | 204 | ||
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 064931aec..6097178b6 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs | |||
@@ -1336,6 +1336,7 @@ pub enum Expr { | |||
1336 | Literal(Literal), | 1336 | Literal(Literal), |
1337 | LoopExpr(LoopExpr), | 1337 | LoopExpr(LoopExpr), |
1338 | MacroCall(MacroCall), | 1338 | MacroCall(MacroCall), |
1339 | MacroStmts(MacroStmts), | ||
1339 | MatchExpr(MatchExpr), | 1340 | MatchExpr(MatchExpr), |
1340 | MethodCallExpr(MethodCallExpr), | 1341 | MethodCallExpr(MethodCallExpr), |
1341 | ParenExpr(ParenExpr), | 1342 | ParenExpr(ParenExpr), |
@@ -3034,6 +3035,9 @@ impl From<LoopExpr> for Expr { | |||
3034 | impl From<MacroCall> for Expr { | 3035 | impl From<MacroCall> for Expr { |
3035 | fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) } | 3036 | fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) } |
3036 | } | 3037 | } |
3038 | impl From<MacroStmts> for Expr { | ||
3039 | fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) } | ||
3040 | } | ||
3037 | impl From<MatchExpr> for Expr { | 3041 | impl From<MatchExpr> for Expr { |
3038 | fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) } | 3042 | fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) } |
3039 | } | 3043 | } |
@@ -3078,8 +3082,8 @@ impl AstNode for Expr { | |||
3078 | match kind { | 3082 | match kind { |
3079 | ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR | 3083 | ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR |
3080 | | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR | 3084 | | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR |
3081 | | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR | 3085 | | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MACRO_STMTS |
3082 | | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR | 3086 | | MATCH_EXPR | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR |
3083 | | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR | 3087 | | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR |
3084 | | YIELD_EXPR => true, | 3088 | | YIELD_EXPR => true, |
3085 | _ => false, | 3089 | _ => false, |
@@ -3105,6 +3109,7 @@ impl AstNode for Expr { | |||
3105 | LITERAL => Expr::Literal(Literal { syntax }), | 3109 | LITERAL => Expr::Literal(Literal { syntax }), |
3106 | LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }), | 3110 | LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }), |
3107 | MACRO_CALL => Expr::MacroCall(MacroCall { syntax }), | 3111 | MACRO_CALL => Expr::MacroCall(MacroCall { syntax }), |
3112 | MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }), | ||
3108 | MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), | 3113 | MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), |
3109 | METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), | 3114 | METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), |
3110 | PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }), | 3115 | PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }), |
@@ -3142,6 +3147,7 @@ impl AstNode for Expr { | |||
3142 | Expr::Literal(it) => &it.syntax, | 3147 | Expr::Literal(it) => &it.syntax, |
3143 | Expr::LoopExpr(it) => &it.syntax, | 3148 | Expr::LoopExpr(it) => &it.syntax, |
3144 | Expr::MacroCall(it) => &it.syntax, | 3149 | Expr::MacroCall(it) => &it.syntax, |
3150 | Expr::MacroStmts(it) => &it.syntax, | ||
3145 | Expr::MatchExpr(it) => &it.syntax, | 3151 | Expr::MatchExpr(it) => &it.syntax, |
3146 | Expr::MethodCallExpr(it) => &it.syntax, | 3152 | Expr::MethodCallExpr(it) => &it.syntax, |
3147 | Expr::ParenExpr(it) => &it.syntax, | 3153 | Expr::ParenExpr(it) => &it.syntax, |