Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I define a macro which defines another macro when the inner macro takes arguments?

Tags:

Minimal code to reproduce:

macro_rules! test {
    ($name:ident: $count:expr) => {
        macro_rules! $name {
            ($($v:expr),*) => {}
        }
    }
}

test!(yo: 123);

Got error:

error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 --> src/lib.rs:4:15
  |
4 |             ($($v:expr),*) => {}
  |               ^^^^^^^^^

Removing $count:expr or changing $count:expr to another type like $count:block omits the error, but I really need it to be expr. What does the error mean?

like image 323
tga Avatar asked Dec 29 '18 16:12

tga


1 Answers

This is a known issue (#35853). The current recommended workaround is to pass in the dollar sign $ as a separate token. You can then call yourself, passing in the $:

macro_rules! test {
    ($name:ident: $count:expr) => { test!($name: $count, $) };

    ($name:ident: $count:expr, $dol:tt) => {
        macro_rules! $name {
            ($dol($v:expr),*) => {}
        }
    };
}

fn main() {
    test!(yo: 2);
    yo!(42);
}
like image 51
Shepmaster Avatar answered Sep 22 '22 09:09

Shepmaster