rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.9k stars 12.68k forks source link

Creating a macro of generating closure, description of arguments to closure in || with a star only works as an exclamation point. #72652

Open denisandroid opened 4 years ago

denisandroid commented 4 years ago

It was expected that I could repeat the syntax of the closure in the macro, I repeated but the rule is not working out correctly.

Code:

macro_rules! test {
    [ | $($args:ident),* | $($block:tt)* ] => {
        | $($args),* | $($block)*
    };
}

fn main() {
    let enc = &test! {
        |a| {
            println!("1");
        }
    } as &'static dyn FnMut(usize);

    let enc2 = &test! {
        || {
            println!("2");
        }
    } as &'static dyn FnMut();
}

Output:

error: no rules expected the token `||`
  --> src/main.rs:16:9
   |
2  | macro_rules! test {
   | ----------------- when calling this macro
...
16 |         || {
   |         ^^ no rules expected this token in macro call

Macro code using one or more elements works, but macro code without elements does not work. Although this is precisely the rule with the star.

Play: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bd27f49b9feeb021af76615321013784

Rust Version: stable 1.43.1 or rustc 1.45.0-nightly (a74d1862d 2020-05-14)

jonas-schievink commented 4 years ago

You need to put a space between the ||. I believe declarative macros do not have access to the individual parts of a "fused" token (unlike procedural macros).

denisandroid commented 4 years ago

Yeah, I noticed that adding a space makes the macro work properly, but that 's not the solution.

I can certainly add a rule with an empty set of arguments, but I turned here to avoid duplicating the code because the rule provides for a star.