lang (macros | syntax)
Add a literal
fragment specifier for macro_rules!
patterns that matches literal constants:
macro_rules! foo {
($l:literal) => ( /* ... */ );
};
There are a lot of macros out there that take literal constants as arguments (often string constants). For now, most use the expr
fragment specifier, which is fine since literal constants are a subset of expressions. But it has the following issues:
expr
specifier. For example $e:expr : $t:ty
is not allowed whereas $l:literal : $t:ty
should be. There is no reason to arbitrarily restrict the syntax of those macros where they will only be actually used with literal constants. A workaround for that is to use the tt
matcher.epxr
it would probably give a syntax or typing error inside the generated code, which is hard to understand.Add a literal
(or lit
, or constant
) matcher in macro patterns that matches all single-tokens literal constants (those that are currently represented by token::Literal
).
Matching input against this matcher would call the parse_lit
method from libsyntax::parse::Parser
. The FOLLOW set of this matcher should be the same as ident
since it matches a single token.
This includes only single-token literal constants and not compound literals, for example struct literals Foo { x: some_literal, y: some_literal }
or arrays [some_literal ; N]
, where some_literal
can itself be a compound literal. See in alternatives why this is disallowed.
$s:str
which expects a literal string, $i:integer
which expects a literal integer, etc. With this design, we could allow something like $s:struct
for compound literals which still requires a lot of work to implement but has the advantage of not ‶polluting″ the FOLLOW sets of other specifiers such as str
. It provides also better ‶static″ (pre-expansion) checking of the arguments of a macro and thus better error reporting. Types are also good for documentation. The main drawback here if of course that we could not allow any possible type since we cannot interleave parsing and type checking, so we would have to define a list of accepted types, for example str
, integer
, bool
, struct
and array
(without specifying the complete type of the structs and arrays). This would be a bit inconsistent since those types indeed refer more to syntactic categories in this context than to true Rust types. It would be frustrating and confusing since it can give the impression that macros do type-checking of their arguments, when of course they don't.expr
or tt
to refer to literal constants.The keyword of the matcher can be literal
, lit
, constant
, or something else.