diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-15 14:45:09 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-15 14:45:09 +0000 |
commit | bd4c352831662762ee7a66da77ec9adf623b0a0a (patch) | |
tree | 725dfad20b95344ad363b35860cf7e57067bb5e5 /crates/parser/src/grammar/items.rs | |
parent | 39aae835fd70d06092c1be1add6eef3984439529 (diff) | |
parent | 479babf8740a4d3cf6fc03a5f4a2fca00d387501 (diff) |
Merge #6893
6893: Move to upstream `macro_rules!` model r=matklad a=jonas-schievink
This changes `macro_rules!` from being treated as a macro invocation to being a first-class item. It also disallows using an additional ident argument for regular macros, so `m! ident(...);` now fails to parse.
This matches upstream Rust, and makes the code somewhat simpler by removing repeated "is this a `macro_rules!` call" checks. It will also simplify allowing visibilities on macros, which is currently being proposed in https://github.com/rust-lang/rust/pull/78166.
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/parser/src/grammar/items.rs')
-rw-r--r-- | crates/parser/src/grammar/items.rs | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index ad29b82f7..8999829b4 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs | |||
@@ -232,6 +232,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> { | |||
232 | T![macro] => { | 232 | T![macro] => { |
233 | macro_def(p, m); | 233 | macro_def(p, m); |
234 | } | 234 | } |
235 | IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => { | ||
236 | macro_rules(p, m); | ||
237 | } | ||
235 | IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { | 238 | IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { |
236 | // test union_items | 239 | // test union_items |
237 | // union Foo {} | 240 | // union Foo {} |
@@ -363,6 +366,34 @@ pub(crate) fn item_list(p: &mut Parser) { | |||
363 | m.complete(p, ITEM_LIST); | 366 | m.complete(p, ITEM_LIST); |
364 | } | 367 | } |
365 | 368 | ||
369 | fn macro_rules(p: &mut Parser, m: Marker) { | ||
370 | assert!(p.at_contextual_kw("macro_rules")); | ||
371 | p.bump_remap(T![macro_rules]); | ||
372 | p.expect(T![!]); | ||
373 | |||
374 | if p.at(IDENT) { | ||
375 | name(p); | ||
376 | } | ||
377 | // Special-case `macro_rules! try`. | ||
378 | // This is a hack until we do proper edition support | ||
379 | |||
380 | // test try_macro_rules | ||
381 | // macro_rules! try { () => {} } | ||
382 | if p.at(T![try]) { | ||
383 | let m = p.start(); | ||
384 | p.bump_remap(IDENT); | ||
385 | m.complete(p, NAME); | ||
386 | } | ||
387 | |||
388 | match p.current() { | ||
389 | T!['{'] => { | ||
390 | token_tree(p); | ||
391 | } | ||
392 | _ => p.error("expected `{`"), | ||
393 | } | ||
394 | m.complete(p, MACRO_RULES); | ||
395 | } | ||
396 | |||
366 | // test macro_def | 397 | // test macro_def |
367 | // macro m { ($i:ident) => {} } | 398 | // macro m { ($i:ident) => {} } |
368 | // macro m($i:ident) {} | 399 | // macro m($i:ident) {} |
@@ -394,19 +425,6 @@ fn macro_call(p: &mut Parser) -> BlockLike { | |||
394 | 425 | ||
395 | pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { | 426 | pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { |
396 | p.expect(T![!]); | 427 | p.expect(T![!]); |
397 | if p.at(IDENT) { | ||
398 | name(p); | ||
399 | } | ||
400 | // Special-case `macro_rules! try`. | ||
401 | // This is a hack until we do proper edition support | ||
402 | |||
403 | // test try_macro_rules | ||
404 | // macro_rules! try { () => {} } | ||
405 | if p.at(T![try]) { | ||
406 | let m = p.start(); | ||
407 | p.bump_remap(IDENT); | ||
408 | m.complete(p, NAME); | ||
409 | } | ||
410 | 428 | ||
411 | match p.current() { | 429 | match p.current() { |
412 | T!['{'] => { | 430 | T!['{'] => { |