Macros
Fragment Specifiers
A fragment specifier (also called a designator) is the type tag after the colon in a macro_rules! metavariable ($name:specifier) that tells the Rust parser which grammatical construct to match and capture.
Complete Reference of macro_rules! Fragment Specifiers
| Specifier | What It Matches | Example Input Tokens |
|---|---|---|
expr |
Any valid Rust expression (Edition 2024 includes const { ... } and _) |
2 + 2, foo(x), if c { 1 } else { 2 } |
expr_2021 |
Expression using pre-2024 rules (excludes standalone const / _ expressions) |
2 + 2, vec.len() |
ident |
An identifier or keyword | foo, Point, self, r#type |
ty |
A type expression | i32, Vec<String>, &'a [u8], impl Send |
pat |
Any pattern (including top-level | or-patterns in 2021/2024) |
Some(x), 1 | 2 | 3, (a, _) |
pat_param |
A single pattern excluding top-level | (allows | as a delimiter after it) |
Some(x), (a, b) |
stmt |
A single statement without its trailing semicolon (except item statements) | let x = 5, x += 1 |
block |
A brace-delimited block expression | { let a = 1; a + 2 } |
item |
A module-level or associated item | fn f() {}, struct S;, use std::io; |
meta |
The contents inside an attribute #[...] |
derive(Debug), allow(dead_code) |
path |
A Type::Style path |
std::collections::HashMap, crate::util::run |
literal |
Any literal expression (including negative numbers like -42) |
"hello", 42, -3.14, 'a', true |
lifetime |
A lifetime token | 'a, 'static, '_ |
vis |
An optional visibility qualifier (matches empty tokens if omitted!) | pub, pub(crate), pub(super), (empty) |
tt |
A single Token Tree: one identifier, literal, punctuation, or balanced (...) / [...] / {...} group |
+, foo, (a + b * c) |
Using vis, ident, ty, and expr Together
Notice that $v:vis is always optional—it matches pub, pub(crate), or nothing at all (0 tokens) when the caller omits visibility:
macro_rules! make_getter {
($v:vis $field:ident : $t:ty = $default:expr) => {
struct Config {
$field: $t,
}
impl Config {
$v fn $field(&self) -> &$t {
&self.$field
}
}
};
}
make_getter!(pub max_connections: usize = 128);
fn main() {
let cfg = Config {
max_connections: 256,
};
println!("max_connections = {}", cfg.max_connections());
}
max_connections = 256
Opaque AST Capture Rule (Cannot Re-Match a Non-tt Fragment)
Once tokens are captured as a structured AST fragment like $e:expr, $t:ty, or $p:pat, they are sealed into an opaque AST node. If you forward $e to another macro rule, that second rule can only match $e as $other:expr or $other:tt—it cannot destructure $e back into individual tokens ($a:ident + $b:ident). If a helper macro needs to inspect raw tokens recursively, capture them as $t:tt first.