Skip to content

$crate is treated as a normal identifier in a macro_rules matcher #147028

@theemathas

Description

@theemathas

I've found that, in some cases, inside a macro_rules matcher (the thing on the left of the =>), $crate is treated as if it's a normal identifier, which seems very weird. I'm not sure if this is intended or a bug.

This weirdness manifests in two different ways:

  1. A $crate on its own in the matcher is treated as literally matching $crate, as opposed to being a metavariable or erroring:
macro_rules! foo {
    ($crate and $crate:tt) => {
        "wtf"
    }
}

macro_rules! bar {
    () => {
        foo!($crate and $crate:tt)
    }
}

fn main() {
    println!("{}", bar!());  // prints "wtf"
}
  1. I can create a metavariable (e.g., the metavariable $x:tt has the name x) such that the metavariable's name is $crate:
macro_rules! bar {
    ($dol:tt) => {
        macro_rules! foo {
            ($dol $crate : expr) => { $dol $crate }
        }
    }
}

bar!($);

fn main() {
    println!("{}", foo!(1 + 2));  // prints 3
}

See also #146967 and #146968 and #146114 for weirdness with $crate.

Meta

Reproducible on the playground with version 1.92.0-nightly (2025-09-24 caccb4d0368bd918ef66)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions