Macros Code Review
by @anderskev
Reviews Rust macro code for hygiene issues, fragment misuse, compile-time impact, and procedural macro patterns. Use when reviewing macro_rules! definitions,...
clawhub install macros-code-reviewπ About This Skill
name: macros-code-review description: "Reviews Rust macro code for hygiene issues, fragment misuse, compile-time impact, and procedural macro patterns. Use when reviewing macro_rules! definitions, procedural macros, derive macros, or attribute macros."
Macros Code Review
Review Workflow
1. Check Cargo.toml -- Note Rust edition (2024 reserves gen keyword, affecting macro output), proc-macro crate dependencies (syn, quote, proc-macro2), and feature flags (e.g., syn with minimal features)
2. Check macro type -- Determine if reviewing declarative (macro_rules!), function-like proc macro, attribute macro, or derive macro
3. Check if a macro is needed -- If the transformation is type-based, generics are better. Macros are for structural/repetitive code generation that generics cannot express
4. Scan macro definitions -- Read full macro bodies including all match arms, not just the invocation site
5. Check each category -- Work through the checklist below, loading references as needed
6. Gates -- Complete Gates below before reporting; do not substitute informal βI verified.β
Gates (before reporting findings)
Complete in order. Do not emit findings until Gate 4 passes for each issue.
Gate 1 β Crate context (on disk)
PASS when: You opened the reviewed crateβs Cargo.toml (workspace member path if applicable) and recorded Rust edition, whether the crate is proc-macro = true, and relevant proc-macro dependencies or syn / quote feature flags.
Blocks rationalization: Edition 2024 findings (gen, unsafe extern, generated unsafe bodies) and syn βfullβ vs minimal flags require this β do not flag edition-specific macro output without matching edition from the file.
Gate 2 β Macro definitions read
PASS when: For every macro you critique, you read the full definition (all macro_rules! arms, or the proc-macro entry plus helpers you rely on), not only call sites or partial expansions.
Artifact: At least one path per macro to the defining .rs file(s) you used.
Gate 3 β Per-finding evidence
PASS when: Each planned issue has [FILE:LINE] from the current tree for the macro definition, attribute/derive site, or generated code location you are discussing (not from memory, docs-only, or another branch).
Gate 4 β Pre-report protocol
PASS when: You loaded and applied beagle-rust:review-verification-protocol, including Macro-Specific Verification for hygiene, fragment type, and proc-macro performance claims. Then add findings.
Output Format
Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
Quick Reference
| Issue Type | Reference | |------------|-----------| | Fragment types, repetition, hygiene, declarative patterns | references/declarative-macros.md | | Proc macro types, syn/quote, spans, testing | references/procedural-macros.md |
Review Checklist
Declarative Macros (macro_rules!)
:expr vs :tt vs :ident -- wrong choice causes unexpected parsing), vs ; vs none, * vs +)$(,)? or $(;)? at end of repetition)#[macro_export]) use $crate:: for crate-internal paths, never crate:: or self::::core:: and ::alloc:: (not ::std::) for no_std compatibilitycompile_error! used for meaningful error messages on invalid input patterns#[macro_export]Procedural Macros
syn features minimized (don't enable full when derive suffices -- reduces compile time)Span::call_site() used for identifiers that should be visible to the callerSpan::mixed_site() used for identifiers private to the macro (matches macro_rules! hygiene)syn::Error with proper spans, not panic!syn::Error::combineproc-macro2 used for testing (testable outside of compiler context)Derive Macros
#[serde(skip)] style) are documentedimpl blocks use fully qualified paths (::core::, $crate::)Attribute Macros
#[test_case] style) produce unique test namesEdition 2024 Awareness
gen as an identifier (reserved keyword -- use r#gen or rename)unsafe fn bodies use explicit unsafe {} blocks around unsafe opsextern blocks use unsafe externGenerics vs Macros
Flag a macro when the same result is achievable with generics or trait bounds. Macros are appropriate when:
const fn cannot expressSeverity Calibration
Critical (Block Merge)
unsafe codeunsafe blocks (caller's variables leak into unsafe context)compile_error! (crashes the compiler)Major (Should Fix)
crate:: or self:: instead of $crate:: (breaks for downstream users)::std:: instead of ::core::/::alloc:: (breaks no_std users):expr where :tt needed, or vice versa)syn full features unnecessarily (compile time cost)compile_error!)Minor (Consider Fixing)
compile_error! fallback arm for invalid patternsInformational (Note Only)
macro_rules! into a proc macroValid Patterns (Do NOT Flag)
macro_rules! for test batteries -- Generating repetitive test modules from a list of types/configsmacro_rules! for trait impls -- Implementing a trait for many concrete types with identical bodies#[macro_export] with $crate -- Correct way to make macros usable outside the defining crateSpan::call_site() for generated functions -- Intentionally making generated items visible to callerssyn::Error::to_compile_error() -- Correct error reporting pattern in proc macrostrybuild tests for proc macros -- Standard compile-fail testing approachcompile_error! in impossible match arms -- Good practice for catching invalid macro input