このページの目次
プロシージャルマクロ (Procedural Macros)
プロシージャルマクロはコンパイル時にRustコードを実行し、TokenStreamを受け取ってTokenStreamを出力します。deriveマクロはstruct/enumに対してimplを自動生成し、attributeマクロは任意の項目を修飾し、function-likeマクロは関数のように呼び出されますがトークンストリームを処理します。synはTokenStreamをASTに解析し、quoteはASTをTokenStreamに戻し、cargo expandは展開結果を確認します。これらはプロシージャルマクロを書くための標準的なワークフローです。
3種類のプロシージャルマクロ
// 1. derive: #[derive(MyTrait)] — 型に対してimplを自動生成
// 2. attribute: #[my_attr] — 項目全体 (fn, struct, impl) を修飾
// 3. function-like: my_macro!(...) — macro_rules! に似ているが、Rust関数で入力を処理
プロシージャルマクロはRustコードであり、コンパイル時に実行され、TokenStream(トークンのシーケンス)を受け取って生成します。これは macro_rules! よりも柔軟性が高く、任意の複雑なコンパイル時の計算を行うことができます。
syn + quote: 事実上の標準
use TokenStream;
use ;
use quote;
syn は TokenStream を AST(Rustコンパイラのフロントエンドのようなもの)に解析します。quote! はRustコードをトークンストリームに戻し、補間(#name)をサポートします。
proc-macro crate の制限
- 別のcrateでなければならない(
Cargo.toml:[lib] proc-macro = true) - procマクロ関数のみをエクスポートでき、通常の関数、型、定数はエクスポートできない
- 依存関係にサイクルを含めることはできない——proc-macro crate は他のcrateに依存できるが、同じワークスペースのcrateから逆依存されることはできない
cargo expand: マクロの展開
マクロの動作を理解するための最速の方法です——コンパイラが実際に処理しているコードを見ることができます。
参考
- syn: docs.rs/syn, quote: docs.rs/quote
- cargo-expand: github.com/dtolnay/cargo-expand
キーワード: proc macro, derive, syn, quote, TokenStream, cargo expand, attribute macro, function-like macro