Auto merge of #13156 - Veykril:macro-stmts, r=Veykril

Remove hir::Expr::MacroStmts

This hir expression isn't needed and only existed as it was simpler to
deal with at first as it gave us a direct mapping for the ast version of
the same construct. This PR removes it, properly handling the statements
that are introduced by macro call expressions.
This commit is contained in:
bors 2022-08-31 16:09:17 +00:00
commit ab068f120b
13 changed files with 68 additions and 118 deletions

View File

@ -550,20 +550,6 @@ impl ExprCollector<'_> {
None => self.alloc_expr(Expr::Missing, syntax_ptr), 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), ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
}) })
} }
@ -640,11 +626,46 @@ impl ExprCollector<'_> {
} }
} }
fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Statement> { fn collect_macro_as_stmt(
&mut self,
statements: &mut Vec<Statement>,
mac: ast::MacroExpr,
) -> 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) => {
expansion.statements().for_each(|stmt| this.collect_stmt(statements, stmt));
expansion.expr().and_then(|expr| match expr {
ast::Expr::MacroExpr(mac) => this.collect_macro_as_stmt(statements, mac),
expr => Some(this.collect_expr(expr)),
})
}
None => None,
},
);
match expansion {
Some(tail) => {
// 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, tail);
Some(tail)
}
None => None,
}
}
fn collect_stmt(&mut self, statements: &mut Vec<Statement>, s: ast::Stmt) {
match s { match s {
ast::Stmt::LetStmt(stmt) => { ast::Stmt::LetStmt(stmt) => {
if self.check_cfg(&stmt).is_none() { if self.check_cfg(&stmt).is_none() {
return None; return;
} }
let pat = self.collect_pat_opt(stmt.pat()); let pat = self.collect_pat_opt(stmt.pat());
let type_ref = let type_ref =
@ -654,61 +675,26 @@ impl ExprCollector<'_> {
.let_else() .let_else()
.and_then(|let_else| let_else.block_expr()) .and_then(|let_else| let_else.block_expr())
.map(|block| self.collect_block(block)); .map(|block| self.collect_block(block));
Some(Statement::Let { pat, type_ref, initializer, else_branch }) statements.push(Statement::Let { pat, type_ref, initializer, else_branch });
} }
ast::Stmt::ExprStmt(stmt) => { ast::Stmt::ExprStmt(stmt) => {
let expr = stmt.expr(); let expr = stmt.expr();
if let Some(expr) = &expr { match &expr {
if self.check_cfg(expr).is_none() { Some(expr) if self.check_cfg(expr).is_none() => return,
return None; _ => (),
}
} }
let has_semi = stmt.semicolon_token().is_some(); let has_semi = stmt.semicolon_token().is_some();
// Note that macro could be expanded to multiple statements // Note that macro could be expanded to multiple statements
if let Some(expr @ ast::Expr::MacroExpr(mac)) = &expr { if let Some(ast::Expr::MacroExpr(mac)) = expr {
let mac_call = mac.macro_call()?; if let Some(expr) = self.collect_macro_as_stmt(statements, mac) {
let syntax_ptr = AstPtr::new(expr); statements.push(Statement::Expr { expr, has_semi })
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 })
} else { } else {
let expr = self.collect_expr_opt(expr); let expr = self.collect_expr_opt(expr);
Some(Statement::Expr { expr, has_semi }) statements.push(Statement::Expr { expr, has_semi });
} }
} }
ast::Stmt::Item(_item) => None, ast::Stmt::Item(_item) => (),
} }
} }
@ -729,9 +715,12 @@ impl ExprCollector<'_> {
let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
let prev_local_module = mem::replace(&mut self.expander.module, module); let prev_local_module = mem::replace(&mut self.expander.module, module);
let mut statements: Vec<_> = let mut statements = Vec::new();
block.statements().filter_map(|s| self.collect_stmt(s)).collect(); block.statements().for_each(|s| self.collect_stmt(&mut statements, s));
let tail = block.tail_expr().and_then(|e| self.maybe_collect_expr(e)); let tail = block.tail_expr().and_then(|e| match e {
ast::Expr::MacroExpr(mac) => self.collect_macro_as_stmt(&mut statements, mac),
expr => self.maybe_collect_expr(expr),
});
let tail = tail.or_else(|| { let tail = tail.or_else(|| {
let stmt = statements.pop()?; let stmt = statements.pop()?;
if let Statement::Expr { expr, has_semi: false } = stmt { if let Statement::Expr { expr, has_semi: false } = stmt {

View File

@ -422,19 +422,6 @@ impl<'a> Printer<'a> {
} }
w!(self, "}}"); 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, "}}");
}
} }
} }

View File

@ -176,9 +176,6 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
scopes.set_scope(expr, *scope); scopes.set_scope(expr, *scope);
match &body[expr] { match &body[expr] {
Expr::MacroStmts { statements, tail } => {
compute_block_scopes(statements, *tail, body, scopes, scope);
}
Expr::Block { statements, tail, id, label } => { Expr::Block { statements, tail, id, label } => {
let mut scope = scopes.new_block_scope(*scope, *id, make_label(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 // Overwrite the old scope for the block expr, so that every block scope can be found

View File

@ -206,10 +206,6 @@ pub enum Expr {
Unsafe { Unsafe {
body: ExprId, body: ExprId,
}, },
MacroStmts {
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Array(Array), Array(Array),
Literal(Literal), Literal(Literal),
Underscore, Underscore,
@ -263,7 +259,7 @@ impl Expr {
Expr::Let { expr, .. } => { Expr::Let { expr, .. } => {
f(*expr); f(*expr);
} }
Expr::MacroStmts { tail, statements } | Expr::Block { statements, tail, .. } => { Expr::Block { statements, tail, .. } => {
for stmt in statements.iter() { for stmt in statements.iter() {
match stmt { match stmt {
Statement::Let { initializer, .. } => { Statement::Let { initializer, .. } => {

View File

@ -969,7 +969,7 @@ impl ExpandTo {
if parent.kind() == MACRO_EXPR if parent.kind() == MACRO_EXPR
&& parent && parent
.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; return ExpandTo::Statements;
} }

View File

@ -794,9 +794,6 @@ impl<'a> InferenceContext<'a> {
None => self.table.new_float_var(), None => self.table.new_float_var(),
}, },
}, },
Expr::MacroStmts { tail, statements } => {
self.infer_block(tgt_expr, statements, *tail, expected)
}
Expr::Underscore => { Expr::Underscore => {
// Underscore expressions may only appear in assignee expressions, // Underscore expressions may only appear in assignee expressions,
// which are handled by `infer_assignee_expr()`, so any underscore // which are handled by `infer_assignee_expr()`, so any underscore

View File

@ -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 !0..6 '1isize': isize
!0..6 '1isize': isize
!0..6 '1isize': isize
39..442 '{ ...!(); }': () 39..442 '{ ...!(); }': ()
73..94 'spam!(...am!())': {unknown} 73..94 'spam!(...am!())': {unknown}
100..119 'for _ ...!() {}': () 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 !0..6 '1isize': isize
!0..6 '1isize': isize
!0..6 '1isize': isize
53..456 '{ ...!(); }': () 53..456 '{ ...!(); }': ()
87..108 'spam!(...am!())': {unknown} 87..108 'spam!(...am!())': {unknown}
114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': ()
@ -312,7 +308,6 @@ fn expr_macro_expanded_in_stmts() {
} }
"#, "#,
expect![[r#" expect![[r#"
!0..8 'leta=();': ()
!3..4 'a': () !3..4 'a': ()
!5..7 '()': () !5..7 '()': ()
57..84 '{ ...); } }': () 57..84 '{ ...); } }': ()
@ -321,7 +316,7 @@ fn expr_macro_expanded_in_stmts() {
} }
#[test] #[test]
fn recurisve_macro_expanded_in_stmts() { fn recursive_macro_expanded_in_stmts() {
check_infer( check_infer(
r#" r#"
macro_rules! ng { macro_rules! ng {
@ -340,11 +335,6 @@ fn recurisve_macro_expanded_in_stmts() {
} }
"#, "#,
expect![[r#" 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}': ()
!3..4 'a': i32 !3..4 'a': i32
!5..6 '3': i32 !5..6 '3': i32
196..237 '{ ...= a; }': () 196..237 '{ ...= a; }': ()
@ -369,8 +359,6 @@ fn recursive_inner_item_macro_rules() {
"#, "#,
expect![[r#" expect![[r#"
!0..1 '1': i32 !0..1 '1': i32
!0..7 'mac!($)': ()
!0..26 'macro_...>{1};}': ()
107..143 '{ ...!(); }': () 107..143 '{ ...!(); }': ()
129..130 'a': i32 129..130 'a': i32
"#]], "#]],

View File

@ -573,7 +573,6 @@ fn issue_6811() {
} }
"#, "#,
expect![[r#" expect![[r#"
!0..16 'let_a=...t_b=1;': ()
!3..5 '_a': i32 !3..5 '_a': i32
!6..7 '1': i32 !6..7 '1': i32
!11..13 '_b': i32 !11..13 '_b': i32
@ -1679,7 +1678,6 @@ fn main() {
#[test] #[test]
fn trailing_empty_macro() { fn trailing_empty_macro() {
cov_mark::check!(empty_macro_in_trailing_position_is_removed);
check_no_mismatches( check_no_mismatches(
r#" r#"
macro_rules! m2 { macro_rules! m2 {

View File

@ -2549,7 +2549,6 @@ impl B for Astruct {}
expect![[r#" expect![[r#"
569..573 'self': Box<[T], A> 569..573 'self': Box<[T], A>
602..634 '{ ... }': Vec<T, A> 602..634 '{ ... }': Vec<T, A>
612..628 'unimpl...ted!()': Vec<T, A>
648..761 '{ ...t]); }': () 648..761 '{ ...t]); }': ()
658..661 'vec': Vec<i32, Global> 658..661 'vec': Vec<i32, Global>
664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global> 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global>

View File

@ -140,11 +140,19 @@ impl SourceAnalyzer {
) -> Option<InFile<ast::Expr>> { ) -> Option<InFile<ast::Expr>> {
let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?; let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
let expanded = db.parse_or_expand(macro_file)?; let expanded = db.parse_or_expand(macro_file)?;
let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
let res = match ast::MacroCall::cast(expanded.clone()) { match stmts.expr()? {
Some(call) => self.expand_expr(db, InFile::new(macro_file, call))?, ast::Expr::MacroExpr(mac) => {
_ => InFile::new(macro_file, ast::Expr::cast(expanded)?), 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) Some(res)
} }

View File

@ -315,7 +315,6 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
| ast::Expr::IndexExpr(_) | ast::Expr::IndexExpr(_)
| ast::Expr::Literal(_) | ast::Expr::Literal(_)
| ast::Expr::MacroExpr(_) | ast::Expr::MacroExpr(_)
| ast::Expr::MacroStmts(_)
| ast::Expr::MethodCallExpr(_) | ast::Expr::MethodCallExpr(_)
| ast::Expr::ParenExpr(_) | ast::Expr::ParenExpr(_)
| ast::Expr::PathExpr(_) | ast::Expr::PathExpr(_)

View File

@ -343,7 +343,6 @@ Expr =
| Literal | Literal
| LoopExpr | LoopExpr
| MacroExpr | MacroExpr
| MacroStmts
| MatchExpr | MatchExpr
| MethodCallExpr | MethodCallExpr
| ParenExpr | ParenExpr

View File

@ -1526,7 +1526,6 @@ pub enum Expr {
Literal(Literal), Literal(Literal),
LoopExpr(LoopExpr), LoopExpr(LoopExpr),
MacroExpr(MacroExpr), MacroExpr(MacroExpr),
MacroStmts(MacroStmts),
MatchExpr(MatchExpr), MatchExpr(MatchExpr),
MethodCallExpr(MethodCallExpr), MethodCallExpr(MethodCallExpr),
ParenExpr(ParenExpr), ParenExpr(ParenExpr),
@ -3342,9 +3341,6 @@ impl From<LoopExpr> for Expr {
impl From<MacroExpr> for Expr { impl From<MacroExpr> for Expr {
fn from(node: MacroExpr) -> Expr { Expr::MacroExpr(node) } 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 { impl From<MatchExpr> for Expr {
fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) } fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) }
} }
@ -3411,7 +3407,6 @@ impl AstNode for Expr {
| LITERAL | LITERAL
| LOOP_EXPR | LOOP_EXPR
| MACRO_EXPR | MACRO_EXPR
| MACRO_STMTS
| MATCH_EXPR | MATCH_EXPR
| METHOD_CALL_EXPR | METHOD_CALL_EXPR
| PAREN_EXPR | PAREN_EXPR
@ -3448,7 +3443,6 @@ impl AstNode for Expr {
LITERAL => Expr::Literal(Literal { syntax }), LITERAL => Expr::Literal(Literal { syntax }),
LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }), LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }), MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }),
MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }),
MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }), PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
@ -3487,7 +3481,6 @@ impl AstNode for Expr {
Expr::Literal(it) => &it.syntax, Expr::Literal(it) => &it.syntax,
Expr::LoopExpr(it) => &it.syntax, Expr::LoopExpr(it) => &it.syntax,
Expr::MacroExpr(it) => &it.syntax, Expr::MacroExpr(it) => &it.syntax,
Expr::MacroStmts(it) => &it.syntax,
Expr::MatchExpr(it) => &it.syntax, Expr::MatchExpr(it) => &it.syntax,
Expr::MethodCallExpr(it) => &it.syntax, Expr::MethodCallExpr(it) => &it.syntax,
Expr::ParenExpr(it) => &it.syntax, Expr::ParenExpr(it) => &it.syntax,