Skip to content

Commit 7736b65

Browse files
committed
Auto merge of rust-lang#15361 - Veykril:eager-macro-inputs, r=Veykril
fix: Expand eager macros to delimited comma separated expression list Prior to this, we were just parsing it as an expression which works fine for `()` and `[]` calls as those are tuple and array expressions respectively, but if tails for `{}` calls which with my recent changes reported errors for such eager macro invocations.
2 parents 429a381 + 7c765d9 commit 7736b65

File tree

10 files changed

+83
-6
lines changed

10 files changed

+83
-6
lines changed

crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ fn main() {
238238
/* error: expected expression */;
239239
/* error: expected expression, expected COMMA */;
240240
/* error: expected expression */::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(), ::core::fmt::Display::fmt), ]);
241-
/* error: expected expression, expected R_PAREN */;
241+
/* error: expected expression, expected expression */;
242242
::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(5), ::core::fmt::Display::fmt), ]);
243243
}
244244
"##]],

crates/hir-expand/src/db.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,13 @@ fn macro_arg_node(
430430
let loc = db.lookup_intern_macro_call(id);
431431
let arg = if let MacroDefKind::BuiltInEager(..) = loc.def.kind {
432432
let res = if let Some(EagerCallInfo { arg, .. }) = loc.eager.as_deref() {
433-
Some(mbe::token_tree_to_syntax_node(&arg.0, mbe::TopEntryPoint::Expr).0)
433+
Some(mbe::token_tree_to_syntax_node(&arg.0, mbe::TopEntryPoint::MacroEagerInput).0)
434434
} else {
435435
loc.kind
436436
.arg(db)
437437
.and_then(|arg| ast::TokenTree::cast(arg.value))
438-
.map(|tt| tt.reparse_as_expr().to_syntax())
438+
.map(|tt| tt.reparse_as_comma_separated_expr().to_syntax())
439439
};
440-
441440
match res {
442441
Some(res) if res.errors().is_empty() => res.syntax_node(),
443442
Some(res) => {

crates/ide-diagnostics/src/handlers/macro_error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ macro_rules! compile_error { () => {} }
5151
5252
compile_error!("compile_error macro works");
5353
//^^^^^^^^^^^^^ error: compile_error macro works
54+
55+
compile_error! { "compile_error macro braced works" }
56+
//^^^^^^^^^^^^^ error: compile_error macro braced works
5457
"#,
5558
);
5659
}

crates/parser/src/grammar.rs

+34
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,40 @@ pub(crate) mod entry {
165165
}
166166
m.complete(p, ERROR);
167167
}
168+
169+
pub(crate) fn eager_macro_input(p: &mut Parser<'_>) {
170+
let m = p.start();
171+
172+
let closing_paren_kind = match p.current() {
173+
T!['{'] => T!['}'],
174+
T!['('] => T![')'],
175+
T!['['] => T![']'],
176+
_ => {
177+
p.error("expected `{`, `[`, `(`");
178+
while !p.at(EOF) {
179+
p.bump_any();
180+
}
181+
m.complete(p, ERROR);
182+
return;
183+
}
184+
};
185+
p.bump_any();
186+
while !p.at(EOF) && !p.at(closing_paren_kind) {
187+
expressions::expr(p);
188+
if !p.at(EOF) && !p.at(closing_paren_kind) {
189+
p.expect(T![,]);
190+
}
191+
}
192+
p.expect(closing_paren_kind);
193+
if p.at(EOF) {
194+
m.complete(p, MACRO_EAGER_INPUT);
195+
return;
196+
}
197+
while !p.at(EOF) {
198+
p.bump_any();
199+
}
200+
m.complete(p, ERROR);
201+
}
168202
}
169203
}
170204

crates/parser/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ pub enum TopEntryPoint {
7575
/// Edge case -- macros generally don't expand to attributes, with the
7676
/// exception of `cfg_attr` which does!
7777
MetaItem,
78+
/// Edge case 2 -- eager macros expand their input to a delimited list of comma separated expressions
79+
MacroEagerInput,
7880
}
7981

8082
impl TopEntryPoint {
@@ -87,6 +89,7 @@ impl TopEntryPoint {
8789
TopEntryPoint::Type => grammar::entry::top::type_,
8890
TopEntryPoint::Expr => grammar::entry::top::expr,
8991
TopEntryPoint::MetaItem => grammar::entry::top::meta_item,
92+
TopEntryPoint::MacroEagerInput => grammar::entry::top::eager_macro_input,
9093
};
9194
let mut p = parser::Parser::new(input);
9295
entry_point(&mut p);

crates/parser/src/syntax_kind/generated.rs

+1
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ pub enum SyntaxKind {
262262
TYPE_BOUND_LIST,
263263
MACRO_ITEMS,
264264
MACRO_STMTS,
265+
MACRO_EAGER_INPUT,
265266
#[doc(hidden)]
266267
__LAST,
267268
}

crates/syntax/rust.ungram

+6
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ TokenTree =
7272
MacroItems =
7373
Item*
7474

75+
MacroEagerInput =
76+
'(' (Expr (',' Expr)* ','?)? ')'
77+
| '{' (Expr (',' Expr)* ','?)? '}'
78+
| '[' (Expr (',' Expr)* ','?)? ']'
79+
80+
7581
MacroStmts =
7682
statements:Stmt*
7783
Expr?

crates/syntax/src/ast/generated/nodes.rs

+30
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,20 @@ pub struct MacroItems {
197197
impl ast::HasModuleItem for MacroItems {}
198198
impl MacroItems {}
199199

200+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
201+
pub struct MacroEagerInput {
202+
pub(crate) syntax: SyntaxNode,
203+
}
204+
impl MacroEagerInput {
205+
pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
206+
pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
207+
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
208+
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
209+
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
210+
pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
211+
pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
212+
}
213+
200214
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
201215
pub struct MacroStmts {
202216
pub(crate) syntax: SyntaxNode,
@@ -1922,6 +1936,17 @@ impl AstNode for MacroItems {
19221936
}
19231937
fn syntax(&self) -> &SyntaxNode { &self.syntax }
19241938
}
1939+
impl AstNode for MacroEagerInput {
1940+
fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EAGER_INPUT }
1941+
fn cast(syntax: SyntaxNode) -> Option<Self> {
1942+
if Self::can_cast(syntax.kind()) {
1943+
Some(Self { syntax })
1944+
} else {
1945+
None
1946+
}
1947+
}
1948+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
1949+
}
19251950
impl AstNode for MacroStmts {
19261951
fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
19271952
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4360,6 +4385,11 @@ impl std::fmt::Display for MacroItems {
43604385
std::fmt::Display::fmt(self.syntax(), f)
43614386
}
43624387
}
4388+
impl std::fmt::Display for MacroEagerInput {
4389+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4390+
std::fmt::Display::fmt(self.syntax(), f)
4391+
}
4392+
}
43634393
impl std::fmt::Display for MacroStmts {
43644394
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43654395
std::fmt::Display::fmt(self.syntax(), f)

crates/syntax/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl SourceFile {
172172
}
173173

174174
impl ast::TokenTree {
175-
pub fn reparse_as_expr(self) -> Parse<ast::Expr> {
175+
pub fn reparse_as_comma_separated_expr(self) -> Parse<ast::MacroEagerInput> {
176176
let tokens = self.syntax().descendants_with_tokens().filter_map(NodeOrToken::into_token);
177177

178178
let mut parser_input = parser::Input::default();
@@ -203,7 +203,7 @@ impl ast::TokenTree {
203203
}
204204
}
205205

206-
let parser_output = parser::TopEntryPoint::Expr.parse(&parser_input);
206+
let parser_output = parser::TopEntryPoint::MacroEagerInput.parse(&parser_input);
207207

208208
let mut tokens =
209209
self.syntax().descendants_with_tokens().filter_map(NodeOrToken::into_token);

crates/syntax/src/tests/ast_src.rs

+1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc {
216216
// macro related
217217
"MACRO_ITEMS",
218218
"MACRO_STMTS",
219+
"MACRO_EAGER_INPUT",
219220
],
220221
};
221222

0 commit comments

Comments
 (0)