Backend
rust-macros
Rust 宏系统技能 — 声明宏(macro_rules!:片段类型符、重复模式、TT muncher、递归)、过程宏(proc-macro crate:derive 宏、属性宏、函数式宏)、第三方工具(syn 解析、quote 生成)、宏调试与 hygiene。基于 The Book ch 19.6 与 Rust Reference(宏章节)。当用户需要减少重复代码、创建 DSL、实现自定义 derive 或理解宏展开时激活。
Rust 宏系统技能 — 声明宏(macro_rules!:片段类型符、重复模式、TT muncher、递归)、过程宏(proc-macro crate:derive 宏、属性宏、函数式宏)、第三方工具(syn 解析、quote 生成)、宏调试与 hygiene。基于 The Book ch 19.6 与 Rust Reference(宏章节)。当用户需要减少重复代码、创建 DSL、实现自定义 derive 或理解宏展开时激活。
基于 The Rust Programming Language ch 19.6 与 Rust Reference(Macros By Example & Procedural Macros)。
#[derive(Debug)])→ 使用 rust-1.93 技能本技能不收集、存储或传输任何用户数据。
// 基础模式
macro_rules! my_vec {
// 匹配空
() => { Vec::new() };
// 匹配 `$elem; $n` — 重复
($elem:expr; $n:expr) => {{
let mut v = Vec::with_capacity($n);
v.resize($n, $elem);
v
}};
// 匹配逗号分隔列表 — $()* 重复
($($x:expr),* $(,)?) => {{
let mut v = Vec::new();
$(v.push($x);)*
v
}};
}
// 片段类型符
// expr → 表达式 ident → 标识符 ty → 类型
// pat → 模式 stmt → 语句 block → 代码块
// item → 项 meta → 属性 tt → token 树(最通用)
// lifetime → 生命周期 literal → 字面量
// 重复操作符
// $()* → 零或多次 $()+ → 一次或多次 $()? → 零或一次
// assert_eq! 模式(来自标准库)
macro_rules! assert_eq {
($left:expr, $right:expr $(,)?) => {
match (&$left, &$right) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
$crate::panicking::assert_failed(
$crate::panicking::AssertKind::Eq,
&*left_val, &*right_val,
$crate::option::Option::None,
);
}
}
}
};
($left:expr, $right:expr, $($arg:tt)+) => { /* ... */ };
}
// 递归解析 token 序列
macro_rules! parse_args {
// 基本情况
() => { Vec::<String>::new() };
// 递归步骤:`--flag value, rest...`
(--$name:ident $val:expr $(, $($rest:tt)*)?) => {{
let mut v = parse_args!($($($rest)*)?);
v.push(format!("--{}={}", stringify!($name), $val));
v
}};
}
// Cargo.toml — 过程宏 crate 配置
// [lib]
// proc-macro = true
//
// [dependencies]
// syn = { version = "2", features = ["full"] }
// quote = "1"
// proc-macro2 = "1"
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, ItemFn};
use quote::quote;
// 1. derive 宏
#[proc_macro_derive(MyTrait)]
pub fn my_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let expanded = quote! {
impl MyTrait for #name {
fn method(&self) {
println!("MyTrait for {}", stringify!(#name));
}
}
};
TokenStream::from(expanded)
}
// 2. 属性宏
#[proc_macro_attribute]
pub fn log_call(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
let name = &input.sig.ident;
let expanded = quote! {
fn #name() {
println!("Called: {}", stringify!(#name));
#input
}
};
TokenStream::from(expanded)
}
// 3. 函数式宏
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {
let sql_str = input.to_string();
let expanded = quote! {
format!("EXPLAIN {sql_str}")
};
TokenStream::from(expanded)
}
// 启用宏跟踪(nightly)
#![feature(trace_macros)]
fn main() {
trace_macros!(true);
let v = vec![1, 2, 3];
trace_macros!(false);
}
// $crate — 始终引用宏定义所在的 crate
// 确保 macro 中使用 $crate:: 而非绝对路径
macro_rules! make_error {
() => {
$crate::MyError::new()
};
}
// 辅助宏
macro_rules! log_syntax {
// nightly 编译时打印展开结果
() => { /* compiler built-in */ };
}
Step 1. 确定宏类型 — 选择声明宏(macro_rules!)还是过程宏(derive/attribute/function-like) Step 2. 编写宏 — 声明宏用匹配+替换;过程宏用 syn 解析 + quote 生成 Step 3. 测试宏展开 — cargo expand 或 trace_macros!() 检查展开结果 Step 4. 处理 hygiene — 使用 $crate 避免命名冲突 Step 5. 完善文档 — 为宏添加文档注释和 doctest 示例 Step 6. 发布 — 过程宏需独立 proc-macro crate,测试不同上下文的行为