rust-macros について
Rust 開発者向けに、宣言的マクロと手続き型マクロの選択、実装、テストを支援するスキルです。生成 API を抑えつつ、展開結果や診断、互換性を扱います。
主な機能
- 01マクロの種類の選択
- 02宣言的マクロの衛生性管理
- 03手続き型マクロの解析と生成
- 04診断と span の処理
- 05展開結果と UI テスト
活用シーン
- 01マクロが適切か判断
- 02derive や属性マクロの実装
- 03受理・拒否される構文のテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ full-stack-skills/ rust-skills --skill rust-macrosインストール後、Claude Code で/rust-macrosを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlexamples/examples.mdexamples/golden-macro/Cargo.tomlexamples/golden-macro/src/lib.rsreferences/references.md詳細
Rust マクロ
関数、トレイト、ジェネリクス、ビルドスクリプトではすっきり表現できない構文変換や機械的な生成には、マクロを使用してください。生成される API は、マクロの実装より小さく、安定したものにしてください。
対象範囲と振り分け
macro_rules!、宣言的 DSL、derive マクロ、属性マクロ、関数形式の手続き型マクロ、構文解析、トークン生成、衛生性、診断、展開テストには、このスキルを使用してください。
通常のジェネリクス設計は rust-stable に、クレート構成と proc-macro のコンパニオンクレートは rust-workspace に、フィーチャーと公開ポリシーは rust-cargo-build に、コンパイルエラーを利用したテスト戦略は rust-testing に、サードパーティ製の Lombok のような derive の使用は rust-lombok-macros に、UniFFI のエクスポート/derive の使用と生成される外部言語バインディングは rust-uniffi-building に振り分けてください。
ワークフロー
1. マクロが適切な境界であることを確認する
まず、代表的な呼び出し例と期待される展開結果を書いてください。診断やコードの追跡をより明確にできる場合は、関数、トレイト、エコシステムにすでに用意されている derive、または小規模な手書き実装を優先してください。サポートする構文、エディション、MSRV、生成される名前、可視性、エラーケース、semver の対象範囲を定義してください。
2. 最小のマクロの種類を選ぶ
| 必要なこと | 手段 |
|---|---|
| Rust のトークンパターンを繰り返す、またはマッチする | macro_rules! |
| 注釈付きの型にトレイトを実装する | derive 手続き型マクロ |
| 注釈付きのアイテムを変換する | 属性手続き型マクロ |
| カスタムトークン呼び出しを解析する | 関数形式の手続き型マクロ |
手続き型マクロには、proc-macro = true の専用クレートを使用してください。生成コードが proc-macro の非公開実装詳細に依存しないよう、共有ランタイムトレイトと型は通常のライブラリークレートに配置してください。
3. 手続き型マクロのクレート名は公開範囲に合わせる
サフィックスはコンパイラー上の要件ではなく、API としての約束と捉えてください。
| 公開するマクロの種類 | 推奨するパッケージサフィックス | 例 |
|---|---|---|
#[proc_macro_derive] のエントリーポイントのみ | -derive、または _derive など、ファミリーで定着している表記 | serde_derive |
| より広範な一式、特に属性マクロまたは関数形式のマクロ、あるいは複数種類のマクロ | -macros | tokio-macros、actix-macros |
| マクロの対象範囲が不明確、または未指定 | 単数形の -macro は避け、より説明的な名前を選ぶ | — |
公開するエントリーポイントがすべて derive マクロの場合は、-derive を選んでください。クレートは、密接に関連する複数の derive を公開してもかまいません。判断基準は正確な数ではなく、マクロの種類です。属性マクロ、関数形式のマクロ、複数種類のマクロを公開する場合、または意図的にパッケージファミリー全般のマクロ集として提供する場合は、-macros を選んでください。
デフォルトでは <name>-derive と <name>-macros の両方を公開しないでください。1 つの proc-macro クレートに、derive、属性、関数形式のマクロをいくつでも登録できます。次のいずれかの構成を優先してください。
<name> # public runtime API or facade; may re-export macros
<name>-derive # derive-only proc-macro crate
<name> # public runtime API or facade; may re-export macros
<name>-macros # general proc-macro collection
<name>-macro-core # optional normal library for parsing and generation logic
ユーザーがそれぞれを独立して導入でき、分割によって依存関係やコンパイル時間が実質的に削減される場合、リリースまたは互換性ポリシーを分離できる場合、または異なる所有範囲を切り分けられる場合に限り、-derive と -macros を別々の公開クレートに分割してください。公開するマクロ名と役割が重複しないようにしてください。マクロの種類ごとに分けたり、名前の対称性を保ったりするだけの理由で分割しないでください。
公開前に、次の点も確認してください。
- クレートファミリーですでに使われている区切り文字に従ってください。Cargo のパッケージ名には
-または_を含められますが、Rust のクレート識別子ではハイフンがアンダースコアに正規化されます。 - ほとんどのユーザーが実装クレートに直接依存すべきでない場合は、ファサードクレートとフィーチャーで制御する再エクスポートを優先してください。
- 公開済みクレートの名前変更は、エコシステムと semver に影響する移行として扱ってください。長期的に意図する対象範囲は早期に選びつつ、実装されていないマクロの種類を予定として掲げないでください。
4. 宣言的マクロを衛生的に実装する
#[macro_export]
macro_rules! string_list {
($($value:expr),* $(,)?) => {{
let mut output = ::std::vec::Vec::new();
$(output.push(::std::string::ToString::to_string(&$value));)*
output
}};
}
- 具体的なマッチャーアームを一般的なアームより先に配置します。
expr、ident、ty、pat、item、meta、path、ttなど、適切なフラグメント指定子を使用します。- 公開構文で意図されている場合に限り、末尾の区切り文字を任意にします。
- 定義元クレートへのパスには
$crateを使用します。 - 評価の繰り返し、隠れたムーブ、予期しない制御フロー、呼び出し元のコードと衝突する識別子を避けます。
- 大きな入力に二次時間の TT マンチャーを使用しないでください。トークン量が問題になる場合は、繰り返し構文または手続き型パーサーを優先します。
5. 手続き型マクロを構造的に解析する
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(Describe)]
pub fn derive_describe(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
quote! {
impl Describe for #name {
fn type_name() -> &'static str {
stringify!(#name)
}
}
}
.into()
}
- トークン文字列ではなく、
synまたは専用のパーサーで解析します。 - スパンを保持し、
syn::Errorの値を結合して、ユーザーに役立つ複数の診断を返します。 - 公開契約で必要な場合は、依存関係の名前変更後も機能するパスを生成します。
- ジェネリクス、ライフタイム、定数パラメーター、where 句、属性、可視性を保持します。
- 無効なユーザー入力でパニックしないでください。該当するスパンにコンパイルエラーを出力します。
6. 公開される展開の契約をテストする
複数のレイヤーを使用します。
cargo fmt --all --check
cargo check --workspace --all-targets --all-features
cargo test --workspace --all-targets --all-features
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo expand --package example-crate
- ランタイムテストとドキュメントテストで、生成されたコードが正常に動作することを確認します。
trybuildまたは同等の UI テストで、受け入れる構文と拒否する構文、および診断を固定します。- 展開結果のスナップショットはレビューの補助であり、唯一の正しさの判定基準にはしません。
- マクロがサポートすると主張するジェネリクス、ライフタイム、可視性、依存関係の名前変更、no-std、機能、エディションの組み合わせをテストします。
Nightly の trace_macros! は任意の診断ツールであり、安定版での既定の手段ではありません。
マッチャーと手続き型マクロの詳細については、マクロのリファレンスを参照してください。代表的なリクエストについては、実行シナリオを参照してください。
レビューチェックリスト
- 関数、トレイト、または derive でマクロを置き換えられますか?
- 呼び出し元の入力は、ドキュメントどおりに正確に評価されますか?
$crate、スパン、ジェネリクス、可視性は適切に処理されていますか?- 無効な入力によって手続き型マクロがパニックする可能性はありますか?
- 生成された unsafe コードは、文書化された安全性の契約を公開していますか?
- 不安定な文言を過度に指定せずに、コンパイル失敗時の診断をテストしていますか?
- 生成される公開 API によって、意図した semver 上の約束が生じますか?
完了条件
- 実装前に、サポートする構文と期待する展開結果を定義します。
- 用途に適した最小限の種類のマクロを使用します。
- 衛生性、スパン、ジェネリクス、可視性、エディションとの互換性を保持します。
- 呼び出し元を想定したテストで、正常な展開と拒否される構文を網羅します。
- サポート対象の構成で、フォーマット、チェック、テスト、Clippy を通過します。
上流の情報源
データプライバシー
このスキルは、ユーザーデータを収集、保存、送信しません。生成されたコードには入力リテラルが埋め込まれる場合があるため、成果物を公開する前に、展開結果に秘密情報が含まれていないか確認してください。