Does the metavariable preserve its fragment-specifier meaning when it is used?

⚓ Rust    📅 2026-02-26    👤 surdeus    👁️ 3      

surdeus

In this example

macro_rules! test_index {
    ($id:ident,$index:literal) => {
        $id.$index
    };
}

fn main() {
    let a = (1, 2);
    test_index!(a, 0);
}

There is an error:

error: unexpected token: `literal` metavariable
 --> src/main.rs:3:13
  |
3 |         $id.$index
  |             ^^^^^^
...
9 |     test_index!(a, 0);
  |     ----------------- in this macro invocation
  |
  = note: this error originates in the macro `test_index` (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable

tuple index syntax states that the tuple index is TUPLE_INDEX, which is a literal.

fragment specifiers defines literal as

I suppose the reason why the compiler reports an error is that $index matches a LiteralExpression; wherever the metavariable is used, it always preserves the information that it is a LiteralExpression. So, the metavariable can only be used where the syntax permits a LiteralExpression to appear.

Instead, the tuple index expects a TUPLE_INDEX in which a LiteralExpression is not permitted to appear. Even though both TUPLE_INDEX and LiteralExpression are sourced from the token(i.e., Literal) 0, they have different syntax meanings. The metavariable preserves its syntax meaning indicated by the fragment specifier.

This is the reason for the error. Is my understanding right?

4 posts - 2 participants

Read full topic

🏷️ Rust_feed