agentsclimarketplace

Rust macros

Skill dawidpereira/rust-skills/skills/rust-macros

Curated Rust skill files for Claude Code: ownership, async, errors, types, architecture, DDD, and more

Install
npx -y skills add dawidpereira/rust-skills --skill rust-macros

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Rust macros — macro_rules!, proc macros, derive macros, attribute macros, fragment specifiers, repetition, hygiene, cargo expand, when to use macros vs generics. Use when writing or debugging declarative or procedural macros, choosing between macros and other abstractions, understanding expansion errors, or generating repetitive code.

SKILL.md

6.5 KB, as published. Nobody here has run it

Macros

Core Question

Is a macro the simplest way to eliminate this repetition, or would a function, generic, or trait do the job?

Macros generate code at compile time. They are powerful but harder to read, debug, and maintain than plain Rust. Reach for them only after ruling out simpler alternatives.


Error → Design Question

SymptomAsk Instead
"no rules expected the token"Does your fragment specifier match the input?
"unexpected end of macro"Are repetition delimiters balanced?
"macro expanded to expression"Does the call site expect a statement or expression?
"local ambiguity"Are your macro arms ordered most-specific-first?
Proc macro panicIs your TokenStream handling all input shapes?
"recursion limit reached"Is recursive expansion necessary, or can you restructure?

Quick Decisions

SituationReach ForWhy
Eliminating repeated struct/enum boilerplatemacro_rules! with repetitionGenerates variants without proc macro overhead
Code generation from attributesDerive proc macroRuns at compile time, integrates with #[derive]
Transforming function signaturesAttribute proc macroFull control over the annotated item
DSL or custom syntaxFunction-like proc macroArbitrary input parsing via syn
2–3 similar match armsJust duplicate the codeMacro not worth the complexity
Generating test casesmacro_rules! with test namesFast to write, easy to extend
Conditional compilationcfg attributes, not macrosBuilt-in, well-understood, no expansion
Debugging macro expansioncargo expandShows fully expanded code
Macro vs generic functionPrefer generic if types differ but logic is sameGenerics are type-checked, macros are not
Macro vs trait default implPrefer trait if behavior varies by typeTrait dispatch is idiomatic Rust
Exporting macros from library#[macro_export] for macro_rules!, re-export for proc macrosEnsures visibility across crate boundaries
Cross-crate proc macrosSeparate -derive or -macros crateProc macros must live in their own crate

Fragment Specifiers

SpecifierMatchesUse When
exprAny expressionValues, function calls, blocks
identIdentifierNames for types, functions, variables
tyTypeType parameters, annotations
patPatternMatch arms, let bindings
ttSingle token treeCatch-all, forwarding tokens
literalLiteral valueStrings, numbers, booleans
pathType pathstd::collections::HashMap
metaAttribute contentsderive(Debug), cfg(test)
itemTop-level itemFunctions, structs, impls
visVisibility qualifierpub, pub(crate), empty
stmtStatementLet bindings, expressions with ;
blockBrace-delimited block{ ... } bodies

Repetition Patterns

Three repetition operators with an optional separator:

macro_rules! make_list {
    // Zero or more
    ( $( $item:expr ),* ) => {
        vec![ $( $item ),* ]
    };
}

macro_rules! require_one {
    // One or more
    ( $( $item:expr ),+ ) => {
        vec![ $( $item ),+ ]
    };
}

macro_rules! optional_label {
    ( $( $label:ident : )? $value:expr ) => {
        println!("{}", $value);
    };
}

Nested repetition handles parallel lists:

macro_rules! impl_from {
    ( $target:ident : $( $source:ty => $variant:ident ),+ ) => {
        $(
            impl From<$source> for $target {
                fn from(val: $source) -> Self {
                    Self::$variant(val)
                }
            }
        )+
    };
}

The Macro vs Generic Decision

  1. Can a function do it? → Use a function.
  2. Can a generic do it? → Use a generic.
  3. Can a trait do it? → Use a trait.
  4. None of the above? → Then use a macro.

Macros are the right tool when you need to:

  • Generate new identifiers or types
  • Repeat code with varying structure (not just types)
  • Create syntax that Rust's type system cannot express
  • Implement a trait for a list of types

macro_rules! Hygiene

Identifiers inside macro_rules! are hygienic — they do not collide with names at the call site. However, this means a macro cannot reference local variables from the caller unless passed in as arguments.

Use $crate to reference items from the defining crate:

#[macro_export]
macro_rules! create_error {
    ( $msg:expr ) => {
        $crate::Error::new($msg)
    };
}

Without $crate, the macro breaks when used from another crate because Error resolves in the caller's namespace.


Usage Scenarios

Scenario 1: "I have 12 structs that all need the same trait impl with minor variations" → Write a macro_rules! with repetition that takes the struct name and the varying parts as parameters. See references/declarative.md for trait impl patterns.

Scenario 2: "I want to generate tests for multiple input/output pairs" → Use macro_rules! to generate #[test] functions with unique names from a list of cases. See references/declarative.md for test generation.

Scenario 3: "I need a #[derive(MyTrait)] that generates methods based on struct fields" → Create a proc macro crate with syn and quote. Parse DeriveInput, iterate fields, emit impl block. See references/procedural.md for derive macro setup.


Reference Files

FileRead When
references/declarative.mdWriting macro_rules!, fragment specifiers, repetition patterns, common recipes, debugging with cargo expand
references/procedural.mdDerive macros, attribute macros, function-like macros, syn/quote, proc macro testing

Cross-References

WhenCheck
Generics as alternative to macrosrust-types → Quick Decisions
Test generation macrosrust-tests → Quick Decisions
cargo expand and lint setuprust-quality → Quick Decisions
Macro naming and documentationrust-api → Quick Decisions

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.