問題一覧に戻る
上級マクロ
問題108: 手続きマクロ入門

手続きマクロはRustコードとして実行され、コンパイル時にASTを操作します。proc_macro crateで定義し、TokenStreamを入出力とします。カスタムderiveは最も一般的な用途で、#[derive(MyTrait)]で自動的にトレイト実装を生成。synでASTを解析し、quoteで新しいコードを生成します。宣言的マクロより強力で、任意の計算やファイルI/Oも可能。serdeやdieselなど多くのcrateがこの機能を活用しています。

// proc_macroライブラリ
// Cargo.toml:
// [lib]
// proc-macro = true

use proc_macro::;
use quote::quote;
use syn::{parse_macro_input, };

// カスタムderive
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.;

let gen = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("Hello, Macro! My name is {}!",
!(#name));
}
}
};

gen.into()
}

// メインコード
// main.rs:
use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;

trait HelloMacro {
fn hello_macro();
}

#[derive()]
struct Pancakes;

fn main() {
Pancakes::hello_macro();
}