引言

Rust 的宏系统是其最强大的元编程工具,分为两大类:声明宏(macro_rules!)和过程宏(Procedural Macros)。声明宏基于模式匹配,适合简单的代码生成场景;过程宏则直接操作抽象语法树(AST),能实现任意复杂的编译时代码变换。本文聚焦过程宏,系统讲解从基础原理到工程落地的完整链路。

1. 过程宏三大类型

过程宏根据用途分为三种形式:

  • 属性宏(Attribute-like):以 #[my_attribute] 形式作用于任意 item,可以替换被标注的整个语法节点。典型用例:#[tokio::main]、#[derive(Serialize)] 的扩展版。
  • 派生宏(Derive macro):以 #[derive(MyTrait)] 形式作用于 struct/enum,为类型自动生成 trait 实现。典型用例:#[derive(Debug, Clone, Serialize, Deserialize)]。
  • 函数形宏(Function-like):以 my_macro!(...) 形式调用,接受任意 token 输入,产生任意输出。典型用例:vec!、println! 的扩展版。

2. TokenStream 与语法树操作

过程宏的核心输入和输出都是 proc_macro::TokenStream(或 proc_macro2::TokenStream)。TokenStream 是词法 token 的序列,不会直接暴露 AST 节点,因此通常需要配合解析库使用。

常用解析工具链:

  • syn:将 TokenStream 解析为强类型的 AST 节点,支持 struct、enum、函数、表达式等任意 Rust 语法结构的精确解析。
  • quote:将 Rust 语法结构 quote 回 TokenStream,提供 quote! 宏和 ToTokens trait。
  • proc-macro2:proc_macro 的包装库,可在非过程宏代码中测试和复用。

3. 派生宏实战:为自定义 Trait 生成实现

假设我们需要为所有结构体自动实现 Describe trait,该 trait 返回描述结构体字段名称和类型的字符串。

定义目标 trait:

trait Describe {
    fn describe() -> String;
}

实现派生宏:

#[proc_macro_derive(Describe)]
fn derive_describe(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    impl_describe(                        
                    
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部