macros-code-review について
宣言的マクロと手続き型マクロを確認するRust開発者向けのコードレビュースキルです。crateの状況把握、定義全体の確認、指摘の根拠、検証ゲートを重視します。
主な機能
- 01マクロ種別ごとのレビュー手順
- 02Cargo.tomlとeditionの確認
- 03宣言的マクロのチェックリスト
- 04手続き型マクロのチェックリスト
- 05根拠と検証ゲート
活用シーン
- 01マージ前のマクロレビュー
- 02生成コードのedition問題の確認
- 03マクロのエラー処理と衛生性の評価
- 04マクロ依存関係と機能フラグの監査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ existential-birds/ beagle --skill macros-code-reviewインストール後、Claude Code で/macros-code-reviewを入力して読み込まれたか確認します。
同梱ファイルreferences/declarative-macros.mdreferences/procedural-macros.md
詳細
マクロのコードレビュー
レビューワークフロー
Cargo.tomlを確認する -- Rustのエディション(2024ではgenが予約語となり、マクロの出力に影響します)、proc-macroクレートの依存関係(syn、quote、proc-macro2)、機能フラグ(例:最小限の機能のみを有効にしたsyn)を確認します- マクロの種類を確認する -- 宣言的マクロ(
macro_rules!)、関数形式のprocマクロ、属性マクロ、またはderiveマクロのいずれをレビューするのかを特定します - マクロが必要か確認する -- 変換が型に基づくものであれば、ジェネリクスのほうが適しています。マクロは、ジェネリクスでは表現できない構造的または反復的なコード生成に使用します
- マクロ定義を調べる -- 呼び出し箇所だけでなく、すべてのマッチアームを含むマクロ本体全体を読みます
- 各カテゴリを確認する -- 必要に応じてリファレンスを読み込み、以下のチェックリストに沿って確認します
- ゲート -- 報告前に以下のゲートを完了します。形式的な「確認済み」で代用しないでください
ゲート(指摘事項を報告する前に)
順番に完了してください。各問題についてゲート4を通過するまで、指摘事項を出力しないでください。
ゲート1 — クレートのコンテキスト(ディスク上)
合格条件: レビュー対象クレートのCargo.toml(該当する場合はワークスペースメンバーのパス)を開き、Rustのedition、クレートがproc-macro = trueかどうか、関連するproc-macroの依存関係またはsyn/quoteの機能フラグを記録していること。
誤った正当化を防ぐ: エディション2024に関する指摘(gen、unsafe extern、生成されたunsafe本体)や、synの「full」と最小限の機能フラグの違いを判断するには、この確認が必要です。ファイルで確認したeditionと照合せずに、エディション固有のマクロ出力を指摘しないでください。
ゲート2 — マクロ定義の確認
合格条件: 指摘対象とするすべてのマクロについて、呼び出し箇所や部分的な展開だけでなく、定義全体(すべてのmacro_rules!アーム、または依拠するproc-macroのエントリポイントとヘルパー)を読んでいること。
記録事項: 参照したマクロ定義が記述されている.rsファイルのパスを、マクロごとに少なくとも1つ記録します。
ゲート3 — 指摘事項ごとの根拠
合格条件: 検討中の各問題について、現在のツリーにおける[FILE:LINE]があり、議論するマクロ定義、属性/deriveの箇所、または生成コードの箇所を示していること(記憶、ドキュメントのみ、または別のブランチに基づくものではないこと)。
ゲート4 — 報告前のプロトコル
合格条件: review-verification-protocolスキルを読み込み、適用していること。これには衛生性、フラグメント型、proc-macroのパフォーマンスに関する主張を扱うマクロ固有の検証が含まれます。その後で指摘事項を追加します。
出力形式
次の形式で指摘事項を報告します。
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
クイックリファレンス
| 問題の種類 | リファレンス |
|---|---|
フラグメント型、反復、衛生性の境界(変数と型)、$crateパス、TTマンクのパターンと再帰制限、フラグメントマッチャーの後続制約、宣言的マクロとprocマクロの選択フロー | references/declarative-macros.md |
procマクロの種類、syn/quote、スパンの衛生性(call_siteとdef_siteとmixed_site)、syn::Error::new_spannedとcombine、parse_quote!とquote!、synの機能監査、trybuild UIテスト | references/procedural-macros.md |
レビューチェックリスト
宣言的マクロ(macro_rules!)
- 適切なフラグメント型を使用している(
:exprと:ttと:identの誤選択は、予期しないパースエラーの原因になります) - 繰り返しの区切り文字が意図した構文と一致している(
,と;と区切りなし、*と+) - 末尾のカンマ/セミコロンに対応している(繰り返しの末尾に
$(,)?または$(;)?を追加) - マッチャーが具体的なものから順に並んでいる(最初に一致したものが採用されます)
- 曖昧な展開がない — 各メタ変数が、展開側で正しい繰り返し階層に現れている
- マクロ内で定義する変数にはマクロ内部の名前を使用している(衛生性によって保護されるのは変数であり、型/モジュール/関数ではありません)
- エクスポートされたマクロ(
#[macro_export])では、クレート内部のパスに$crate::を使用し、crate::やself::は使用していない -
no_stdとの互換性のため、標準ライブラリのパスには::core::と::alloc::を使用している(::std::は使用しない) - 無効な入力パターンに対して、意味のあるエラーメッセージを表示するために
compile_error!を使用している -
#[macro_export]の場合を除き、マクロの配置がテキスト上のスコープ規則(使用箇所より前に定義)に従っている
手続き型マクロ
-
synの機能を最小限にしている(deriveで十分な場合にfullを有効にしない — コンパイル時間を短縮できます) - 入力トークンから出力トークンへスパンを引き継いでいる(エラーがマクロ内部ではなく、ユーザーコードを指します)
- 導入するヘルパー変数には
Span::mixed_site()をデフォルトで使用している —call_siteはユーザーコードを意図的に指す場合に限り使用し、def_siteはproc_macro::Spanでは nightly 専用です - エラー報告には問題のある AST ノードを指定した
syn::Error::new_spanned(node, msg)を使用し、panic!は使用していない -
syn::Error::combineを使って複数のエラーを収集し、まとめて報告している(最初のエラーで停止するよりもユーザー体験が向上します) - 結果を後続の AST 操作に使用するため
syn::Tが必要な場合は、quote!ではなくparse_quote!を使用している。失敗する可能性がある場合はsyn::parse2(quote!{...})を使用している - 公開型は
proc_macroではなくproc_macro2から再エクスポートしている(下流の利用者との互換性のため) - テストには
proc-macro2を使用している(コンパイラーのコンテキスト外でもテスト可能です) - 生成されるコード量が適切である — 大量のコードを出力する手続き型マクロはコンパイル時間を増大させます
derive マクロ
- 導出される機能が明確である — 開発者がトレイト名だけから動作を推測できます
- ヘルパー属性(
#[serde(skip)]形式)が文書化されている - すべてのバリアント形状(ユニット、タプル、構造体バリアント)でトレイト実装が正しい
- 生成される
implブロックで完全修飾パス(::core::、$crate::)を使用している
属性マクロ
- 入力項目が保持されているか、意図的に変換されている(誤って破棄されていない)
- 属性引数が明確なエラーメッセージとともに検証されている
- テスト生成パターン(
#[test_case]形式)が一意のテスト名を生成している - フレームワークのアノテーションで、生成するコードを説明している
Edition 2024 への対応
- マクロ出力で識別子として
genを使用していない(予約語です —r#genを使うか、名前を変更してください) - 生成される
unsafe fnの本体で、危険な操作を明示的なunsafe {}ブロックで囲んでいる - 生成される
externブロックがunsafe externを使用している
ジェネリクスとマクロの比較
ジェネリクスやトレイト境界で同じ結果を実現できる場合は、マクロにフラグを立ててください。マクロが適切なのは、次の場合です。
- 生成されるコードの構造が変わる場合(型だけによる違いではない)
- 多数の具体型に対する、繰り返しのトレイト実装
- 構成バリエーションを含むテスト一式
const fnでは表現できないコンパイル時の計算
重大度の基準
致命的(マージをブロック)
- マクロが健全でない
unsafeコードを生成する unsafeブロックを出力するマクロで衛生性に違反している(呼び出し元の変数がunsafeコンテキストに漏れ込む)- 手続き型マクロが
compile_error!を返さずにパニックする(コンパイラーがクラッシュします) - derive マクロが誤ったトレイト実装を生成する(トレイトの契約に違反します)
重大(修正すべき)
- エクスポートされたマクロで
$crate::ではなくcrate::またはself::を使用している(利用側のクレートで問題が発生します) - エクスポートされたマクロで
::core::/::alloc::ではなく::std::を使用している(no_stdの利用者で問題が発生します) - フラグメントの型が誤っており、予期しないパースが発生する(
:ttが必要な箇所で:exprを使用している、またはその逆) - Proc マクロで
synのfullフィーチャーを不必要に有効にしている(コンパイル時間が増加します) - スパンの伝播がなく、エラーが呼び出し箇所ではなくマクロ定義を指している
- Proc マクロにエラー処理がなく、不正な入力で
compile_error!ではなくパニックする
軽微(修正を検討)
- 繰り返しパターンで末尾のカンマ/セミコロンを許容していない
- マッチャーのアームが、最も具体的なものから順に並んでいない
- ジェネリクスのほうが明快で同等の表現力を持つ箇所で、マクロを使用している
- 無効なパターンに対する
compile_error!のフォールバックアームがない - ヘルパー属性が文書化されていない
情報提供(注記のみ)
- 複雑な
macro_rules!をProc マクロに分割する提案 - 生成されるコード量を削減する提案
- 簡略化できる可能性のあるTTマーチングやプッシュダウン蓄積パターン
有効なパターン(指摘しないこと)
- テストバッテリー用の
macro_rules!-- 型や設定のリストから、繰り返しのテストモジュールを生成する - トレイト実装用の
macro_rules!-- 同一の本体を持つトレイトを、多数の具体型に実装する - TTマーチング -- 再帰的なトークン処理に有効な高度なパターン
- プッシュダウン蓄積 -- 再帰呼び出しを通じて出力を段階的に構築する有効なパターン
$crateを使用する#[macro_export]-- マクロを定義元のクレート外から利用可能にする正しい方法- 生成関数での
Span::call_site()-- 生成された項目を意図的に呼び出し側から見えるようにする syn::Error::to_compile_error()-- Proc マクロでの正しいエラー報告パターン- Proc マクロの
trybuildテスト -- 標準的なコンパイル失敗テストの手法 - テスト関数への属性マクロ -- テストのセットアップ/ティアダウンでよく使われるパターン
- 実現不可能なマッチアームでの
compile_error!-- 無効なマクロ入力を検出するための望ましい方法