[−][src]Crate defile
::defile
Helper proc-macro to "ungroup" a captured metavariable (thus potentially breaking their hygiene, hence the name).
This is useful when using helper macro_rules
macros, that need to parse using some special rule (e.g. :expr
, :path
, :pat
), but that later want to further inspect the captured variable.
This is not something a macro_rules!
can do on its own, since such so-called metavariables are seen as an opaque single token (:tt
) (the sequence of tokens captured in the metavariable have been grouped (≈ parenthesized) but using invsibile parenthesis.
Example
macro_rules! check_expr { ( 42 ) => ({ println!("Got `42`!"); }); ( $($tt:tt)* ) => ({ println!("Did not get `42`. Instead, got the following tokens:\n["); $( println!(" `{}`,", stringify!($tt)); )* println!("]"); }); } macro_rules! check_all_exprs {( $( $expr:expr // use :expr to be able to use `,` as a delimiter ),* $(,)? ) => ( fn main () { $( println!("vvvvvvvvvvvvv"); check_expr!($expr); println!("^^^^^^^^^^^^^\n"); )* } )} check_all_exprs!(42, 1 + 1);
outputs:
vvvvvvvvvvvvv
Did not get `42`. Instead, got the following tokens:
[
`42`,
]
^^^^^^^^^^^^^
vvvvvvvvvvvvv
Did not get `42`. Instead, got the following tokens:
[
`1 + 1`,
]
^^^^^^^^^^^^^
-
That is:
-
the token
42
not match42
! -
That being said, the expression
1 + 1
is viewed as a single indivisible token too.Indeed, that's kind of the point of this behavior: if we do
2 * $expr
where$expr
captures1 + 1
we expect the result to be2 * (1 + 1)
instead of2 * 1 + 1
!
-
But by doing:
macro_rules! check_all_exprs {(
$(
$expr:expr // use :expr to be able to use `,` as a delimiter
),* $(,)?
- ) => (
+ ) => (::defile::item! {
fn main () {
$(
println!("vvvvvvvvvvvvv");
check_expr!(@$expr); // put `@` before a metavariable to ungroup it
println!("^^^^^^^^^^^^^\n");
)*
}
- )}
+ })}
we do get:
vvvvvvvvvvvvv
Got `42`!
^^^^^^^^^^^^^
vvvvvvvvvvvvv
Did not get `42`. Instead, got the following tokens:
[
`1`,
`+`,
`1`,
]
^^^^^^^^^^^^^
42
has matched the literal 42, but be aware that this has also resulted in1 + 1
getting split. So, if you were todefile
expressions such as2 * @$expr
, you may not obtain the expected result! Use with caution.
Caveats
Currently (1.45.0
), there are several bugs regarding the interaction between
macro_rules!
macros and procedural macros, that may lead to defile!
and any
other helper procedural macro to split groups that are not @
-prefixed.
Hopefully those bugs are solved, making the actual implementation of defile!
meaningful.
Macros
expr | Macro to be used to expand to an expression. |
item | Macro to be used to expand to an item definition. |