about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/body/lower.rs126
-rw-r--r--crates/hir-def/src/body/pretty.rs13
-rw-r--r--crates/hir-def/src/body/scope.rs3
-rw-r--r--crates/hir-def/src/expr.rs6
-rw-r--r--crates/hir-expand/src/lib.rs2
-rw-r--r--crates/hir-ty/src/infer/expr.rs3
-rw-r--r--crates/hir-ty/src/tests/macros.rs17
-rw-r--r--crates/hir-ty/src/tests/regression.rs3
-rw-r--r--crates/hir/src/source_analyzer.rs16
-rw-r--r--crates/ide-db/src/syntax_helpers/node_ext.rs1
-rw-r--r--crates/syntax/rust.ungram1
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs7
12 files changed, 88 insertions, 110 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index f6ec8bf7e9e..cb6fdbfc562 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -550,20 +550,6 @@ impl ExprCollector<'_> {
                     None => self.alloc_expr(Expr::Missing, syntax_ptr),
                 }
             }
-            ast::Expr::MacroStmts(e) => {
-                let statements: Box<[_]> =
-                    e.statements().filter_map(|s| self.collect_stmt(s)).collect();
-                let tail = e.expr().map(|e| self.collect_expr(e));
-
-                if e.syntax().children().next().is_none() {
-                    // HACK: make sure that macros that expand to nothing aren't treated as a `()`
-                    // expression when used in block tail position.
-                    cov_mark::hit!(empty_macro_in_trailing_position_is_removed);
-                    return None;
-                }
-
-                self.alloc_expr(Expr::MacroStmts { tail, statements }, syntax_ptr)
-            }
             ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
         })
     }
@@ -640,7 +626,58 @@ impl ExprCollector<'_> {
         }
     }
 
-    fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Statement> {
+    fn collect_macro_as_stmt(
+        &mut self,
+        mac: ast::MacroExpr,
+    ) -> Option<(Vec<Statement>, Option<ExprId>)> {
+        let mac_call = mac.macro_call()?;
+        let syntax_ptr = AstPtr::new(&ast::Expr::from(mac));
+        let macro_ptr = AstPtr::new(&mac_call);
+        let expansion = self.collect_macro_call(
+            mac_call,
+            macro_ptr,
+            false,
+            |this, expansion: Option<ast::MacroStmts>| match expansion {
+                Some(expansion) => {
+                    let mut statements: Vec<_> = expansion
+                        .statements()
+                        .filter_map(|stmt| this.collect_stmt(stmt))
+                        .flatten()
+                        .collect();
+                    let tail = expansion.expr().and_then(|expr| match expr {
+                        ast::Expr::MacroExpr(mac) => {
+                            let (stmts, tail) = this.collect_macro_as_stmt(mac)?;
+                            statements.extend(stmts);
+                            tail
+                        }
+                        expr => Some(this.collect_expr(expr)),
+                    });
+                    Some((statements, tail))
+                }
+                None => None,
+            },
+        );
+        let mut stmts = Vec::new();
+        let expr = match expansion {
+            Some((statements, tail)) => {
+                stmts.extend(statements);
+                // Make the macro-call point to its expanded expression so we can query
+                // semantics on syntax pointers to the macro
+                let src = self.expander.to_source(syntax_ptr);
+                match tail {
+                    Some(tail) => {
+                        self.source_map.expr_map.insert(src, tail);
+                        tail
+                    }
+                    None => self.make_expr(Expr::Missing, Ok(src.clone())),
+                }
+            }
+            None => self.alloc_expr(Expr::Missing, syntax_ptr),
+        };
+        Some((stmts, Some(expr)))
+    }
+
+    fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
         match s {
             ast::Stmt::LetStmt(stmt) => {
                 if self.check_cfg(&stmt).is_none() {
@@ -654,7 +691,7 @@ impl ExprCollector<'_> {
                     .let_else()
                     .and_then(|let_else| let_else.block_expr())
                     .map(|block| self.collect_block(block));
-                Some(Statement::Let { pat, type_ref, initializer, else_branch })
+                Some(vec![Statement::Let { pat, type_ref, initializer, else_branch }])
             }
             ast::Stmt::ExprStmt(stmt) => {
                 let expr = stmt.expr();
@@ -665,47 +702,15 @@ impl ExprCollector<'_> {
                 }
                 let has_semi = stmt.semicolon_token().is_some();
                 // Note that macro could be expanded to multiple statements
-                if let Some(expr @ ast::Expr::MacroExpr(mac)) = &expr {
-                    let mac_call = mac.macro_call()?;
-                    let syntax_ptr = AstPtr::new(expr);
-                    let macro_ptr = AstPtr::new(&mac_call);
-                    let stmt = self.collect_macro_call(
-                        mac_call,
-                        macro_ptr,
-                        false,
-                        |this, expansion: Option<ast::MacroStmts>| match expansion {
-                            Some(expansion) => {
-                                let statements = expansion
-                                    .statements()
-                                    .filter_map(|stmt| this.collect_stmt(stmt))
-                                    .collect();
-                                let tail = expansion.expr().map(|expr| this.collect_expr(expr));
-
-                                let mac_stmts = this.alloc_expr(
-                                    Expr::MacroStmts { tail, statements },
-                                    AstPtr::new(&ast::Expr::MacroStmts(expansion)),
-                                );
-
-                                Some(mac_stmts)
-                            }
-                            None => None,
-                        },
-                    );
-
-                    let expr = match stmt {
-                        Some(expr) => {
-                            // Make the macro-call point to its expanded expression so we can query
-                            // semantics on syntax pointers to the macro
-                            let src = self.expander.to_source(syntax_ptr);
-                            self.source_map.expr_map.insert(src, expr);
-                            expr
-                        }
-                        None => self.alloc_expr(Expr::Missing, syntax_ptr),
-                    };
-                    Some(Statement::Expr { expr, has_semi })
+                if let Some(ast::Expr::MacroExpr(mac)) = expr {
+                    let (mut statements, tail) = self.collect_macro_as_stmt(mac)?;
+                    if let Some(expr) = tail {
+                        statements.push(Statement::Expr { expr, has_semi });
+                    }
+                    Some(statements)
                 } else {
                     let expr = self.collect_expr_opt(expr);
-                    Some(Statement::Expr { expr, has_semi })
+                    Some(vec![Statement::Expr { expr, has_semi }])
                 }
             }
             ast::Stmt::Item(_item) => None,
@@ -730,8 +735,15 @@ impl ExprCollector<'_> {
         let prev_local_module = mem::replace(&mut self.expander.module, module);
 
         let mut statements: Vec<_> =
-            block.statements().filter_map(|s| self.collect_stmt(s)).collect();
-        let tail = block.tail_expr().and_then(|e| self.maybe_collect_expr(e));
+            block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
+        let tail = block.tail_expr().and_then(|e| match e {
+            ast::Expr::MacroExpr(mac) => {
+                let (stmts, tail) = self.collect_macro_as_stmt(mac)?;
+                statements.extend(stmts);
+                tail
+            }
+            expr => self.maybe_collect_expr(expr),
+        });
         let tail = tail.or_else(|| {
             let stmt = statements.pop()?;
             if let Statement::Expr { expr, has_semi: false } = stmt {
diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs
index ddd476efe5c..f2fed954444 100644
--- a/crates/hir-def/src/body/pretty.rs
+++ b/crates/hir-def/src/body/pretty.rs
@@ -422,19 +422,6 @@ impl<'a> Printer<'a> {
                 }
                 w!(self, "}}");
             }
-            Expr::MacroStmts { statements, tail } => {
-                w!(self, "{{ // macro statements");
-                self.indented(|p| {
-                    for stmt in statements.iter() {
-                        p.print_stmt(stmt);
-                    }
-                    if let Some(tail) = tail {
-                        p.print_expr(*tail);
-                    }
-                });
-                self.newline();
-                w!(self, "}}");
-            }
         }
     }
 
diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs
index f4c390dce26..9b28e38029e 100644
--- a/crates/hir-def/src/body/scope.rs
+++ b/crates/hir-def/src/body/scope.rs
@@ -176,9 +176,6 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
 
     scopes.set_scope(expr, *scope);
     match &body[expr] {
-        Expr::MacroStmts { statements, tail } => {
-            compute_block_scopes(statements, *tail, body, scopes, scope);
-        }
         Expr::Block { statements, tail, id, label } => {
             let mut scope = scopes.new_block_scope(*scope, *id, make_label(label));
             // Overwrite the old scope for the block expr, so that every block scope can be found
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index 4381b43c258..419d3feec3b 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -206,10 +206,6 @@ pub enum Expr {
     Unsafe {
         body: ExprId,
     },
-    MacroStmts {
-        statements: Box<[Statement]>,
-        tail: Option<ExprId>,
-    },
     Array(Array),
     Literal(Literal),
     Underscore,
@@ -263,7 +259,7 @@ impl Expr {
             Expr::Let { expr, .. } => {
                 f(*expr);
             }
-            Expr::MacroStmts { tail, statements } | Expr::Block { statements, tail, .. } => {
+            Expr::Block { statements, tail, .. } => {
                 for stmt in statements.iter() {
                     match stmt {
                         Statement::Let { initializer, .. } => {
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index d753d88470c..fc128102f22 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -969,7 +969,7 @@ impl ExpandTo {
         if parent.kind() == MACRO_EXPR
             && parent
                 .parent()
-                .map_or(true, |p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS))
+                .map_or(false, |p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS))
         {
             return ExpandTo::Statements;
         }
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 2a13106390d..a42a00ea598 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -794,9 +794,6 @@ impl<'a> InferenceContext<'a> {
                     None => self.table.new_float_var(),
                 },
             },
-            Expr::MacroStmts { tail, statements } => {
-                self.infer_block(tgt_expr, statements, *tail, expected)
-            }
             Expr::Underscore => {
                 // Underscore expressions may only appear in assignee expressions,
                 // which are handled by `infer_assignee_expr()`, so any underscore
diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs
index a1ab6060e79..a1a2fdd1fb2 100644
--- a/crates/hir-ty/src/tests/macros.rs
+++ b/crates/hir-ty/src/tests/macros.rs
@@ -193,8 +193,6 @@ fn expr_macro_def_expanded_in_various_places() {
             !0..6 '1isize': isize
             !0..6 '1isize': isize
             !0..6 '1isize': isize
-            !0..6 '1isize': isize
-            !0..6 '1isize': isize
             39..442 '{     ...!(); }': ()
             73..94 'spam!(...am!())': {unknown}
             100..119 'for _ ...!() {}': ()
@@ -276,8 +274,6 @@ fn expr_macro_rules_expanded_in_various_places() {
             !0..6 '1isize': isize
             !0..6 '1isize': isize
             !0..6 '1isize': isize
-            !0..6 '1isize': isize
-            !0..6 '1isize': isize
             53..456 '{     ...!(); }': ()
             87..108 'spam!(...am!())': {unknown}
             114..133 'for _ ...!() {}': ()
@@ -312,16 +308,16 @@ fn expr_macro_expanded_in_stmts() {
         }
         "#,
         expect![[r#"
-            !0..8 'leta=();': ()
             !3..4 'a': ()
             !5..7 '()': ()
             57..84 '{     ...); } }': ()
+            63..82 'id! { ... (); }': ()
         "#]],
     );
 }
 
 #[test]
-fn recurisve_macro_expanded_in_stmts() {
+fn recursive_macro_expanded_in_stmts() {
     check_infer(
         r#"
         macro_rules! ng {
@@ -340,11 +336,7 @@ fn recurisve_macro_expanded_in_stmts() {
         }
         "#,
         expect![[r#"
-            !0..7 'leta=3;': ()
-            !0..13 'ng!{[leta=3]}': ()
-            !0..13 'ng!{[leta=]3}': ()
-            !0..13 'ng!{[leta]=3}': ()
-            !0..13 'ng!{[let]a=3}': ()
+            !0..13 'ng!{[leta=3]}': {unknown}
             !3..4 'a': i32
             !5..6 '3': i32
             196..237 '{     ...= a; }': ()
@@ -369,8 +361,7 @@ fn recursive_inner_item_macro_rules() {
         "#,
         expect![[r#"
             !0..1 '1': i32
-            !0..7 'mac!($)': ()
-            !0..26 'macro_...>{1};}': ()
+            !0..7 'mac!($)': {unknown}
             107..143 '{     ...!(); }': ()
             129..130 'a': i32
         "#]],
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index c7895db1afb..cc49c3d45fc 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -573,12 +573,12 @@ fn issue_6811() {
         }
         "#,
         expect![[r#"
-            !0..16 'let_a=...t_b=1;': ()
             !3..5 '_a': i32
             !6..7 '1': i32
             !11..13 '_b': i32
             !14..15 '1': i32
             103..131 '{     ...!(); }': ()
+            109..128 'profil...ion!()': {unknown}
         "#]],
     );
 }
@@ -1679,7 +1679,6 @@ fn main() {
 
 #[test]
 fn trailing_empty_macro() {
-    cov_mark::check!(empty_macro_in_trailing_position_is_removed);
     check_no_mismatches(
         r#"
 macro_rules! m2 {
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index bd35af06e23..342912b678a 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -140,11 +140,19 @@ impl SourceAnalyzer {
     ) -> Option<InFile<ast::Expr>> {
         let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
         let expanded = db.parse_or_expand(macro_file)?;
-
-        let res = match ast::MacroCall::cast(expanded.clone()) {
-            Some(call) => self.expand_expr(db, InFile::new(macro_file, call))?,
-            _ => InFile::new(macro_file, ast::Expr::cast(expanded)?),
+        let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
+            match stmts.expr()? {
+                ast::Expr::MacroExpr(mac) => {
+                    self.expand_expr(db, InFile::new(macro_file, mac.macro_call()?))?
+                }
+                expr => InFile::new(macro_file, expr),
+            }
+        } else if let Some(call) = ast::MacroCall::cast(expanded.clone()) {
+            self.expand_expr(db, InFile::new(macro_file, call))?
+        } else {
+            InFile::new(macro_file, ast::Expr::cast(expanded)?)
         };
+
         Some(res)
     }
 
diff --git a/crates/ide-db/src/syntax_helpers/node_ext.rs b/crates/ide-db/src/syntax_helpers/node_ext.rs
index 84bde4d44db..b890e2b58df 100644
--- a/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -315,7 +315,6 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
         | ast::Expr::IndexExpr(_)
         | ast::Expr::Literal(_)
         | ast::Expr::MacroExpr(_)
-        | ast::Expr::MacroStmts(_)
         | ast::Expr::MethodCallExpr(_)
         | ast::Expr::ParenExpr(_)
         | ast::Expr::PathExpr(_)
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 62aa4783994..89479543545 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -343,7 +343,6 @@ Expr =
 | Literal
 | LoopExpr
 | MacroExpr
-| MacroStmts
 | MatchExpr
 | MethodCallExpr
 | ParenExpr
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 8c4825ad69e..449402e5f5b 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1526,7 +1526,6 @@ pub enum Expr {
     Literal(Literal),
     LoopExpr(LoopExpr),
     MacroExpr(MacroExpr),
-    MacroStmts(MacroStmts),
     MatchExpr(MatchExpr),
     MethodCallExpr(MethodCallExpr),
     ParenExpr(ParenExpr),
@@ -3342,9 +3341,6 @@ impl From<LoopExpr> for Expr {
 impl From<MacroExpr> for Expr {
     fn from(node: MacroExpr) -> Expr { Expr::MacroExpr(node) }
 }
-impl From<MacroStmts> for Expr {
-    fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) }
-}
 impl From<MatchExpr> for Expr {
     fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) }
 }
@@ -3411,7 +3407,6 @@ impl AstNode for Expr {
                 | LITERAL
                 | LOOP_EXPR
                 | MACRO_EXPR
-                | MACRO_STMTS
                 | MATCH_EXPR
                 | METHOD_CALL_EXPR
                 | PAREN_EXPR
@@ -3448,7 +3443,6 @@ impl AstNode for Expr {
             LITERAL => Expr::Literal(Literal { syntax }),
             LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
             MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }),
-            MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }),
             MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
             METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
             PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
@@ -3487,7 +3481,6 @@ impl AstNode for Expr {
             Expr::Literal(it) => &it.syntax,
             Expr::LoopExpr(it) => &it.syntax,
             Expr::MacroExpr(it) => &it.syntax,
-            Expr::MacroStmts(it) => &it.syntax,
             Expr::MatchExpr(it) => &it.syntax,
             Expr::MethodCallExpr(it) => &it.syntax,
             Expr::ParenExpr(it) => &it.syntax,