
M04 Zero Cost
Resolve Rust generics and trait errors with a clear static-vs-dynamic dispatch decision tree instead of blindly adding trait bounds.
Overview
m04-zero-cost is an agent skill for the Build phase that guides Rust zero-cost abstraction choices between generics and trait objects when trait-bound and type errors appear.
Install
npx skills add https://github.com/zhanghandong/rust-skills --skill m04-zero-costWhat is this skill?
- Maps compiler errors (E0277, E0308, E0599, E0038) to design questions instead of one-line fixes
- Decision flow: compile-time vs runtime polymorphism, generics vs trait objects
- Thinking prompt before trait bounds: trait vs enum vs concrete type
- Trace-up guidance when the type system fights the intended abstraction
- Triggers on monomorphization, impl Trait, dyn, where clauses, and static/dynamic dispatch
- Maps 4 compiler error families (E0277, E0308, E0599, E0038) to design questions
- 3-step thinking prompt before adding trait bounds
Adoption & trust: 753 installs on skills.sh; 1.2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are stuck in a loop of adding trait bounds and still getting E0277, E0308, or E0599 without knowing if you chose the wrong abstraction level.
Who is it for?
Solo builders writing Rust libraries or services who want compile-time performance without defaulting to trait objects everywhere.
Skip if: Teams not using Rust, greenfield architecture-only sessions with no compiler errors, or frontend-only JavaScript work.
When should I use this skill?
CRITICAL: generics, traits, zero-cost abstraction; triggers E0277, E0308, E0599, generic, trait, impl, dyn, where, monomorphization, impl Trait, trait bound not satisfied.
What do I get? / Deliverables
After running the skill, you pick static or dynamic dispatch with aligned types and trait design, and your agent applies bounds only where the abstraction model requires them.
- Chosen abstraction model (generics, enum, concrete, or trait object) with rationale
- Targeted type/trait changes aligned to static or dynamic dispatch
Recommended Skills
Journey fit
Rust type-system and zero-cost abstraction choices happen while implementing libraries and services, not during idea or launch work. Backend and systems Rust code is where E0277/E0308/E0599 and trait-object trade-offs surface during implementation.
How it compares
Use as structured Rust type-system reasoning instead of asking the agent to “just add Send + Sync” on every error.
Common Questions / FAQ
Who is m04-zero-cost for?
Indie and solo developers building in Rust who hit generics, traits, or dispatch errors and want design-level answers before patching types.
When should I use m04-zero-cost?
During Build when you see trait bound not satisfied, mismatched types around impl/dyn, missing trait methods, or object-safety errors—or when choosing generics versus trait objects for a new module.
Is m04-zero-cost safe to install?
Review the Security Audits panel on this Prism page and the zhanghandong/rust-skills source before trusting it in automated agent runs.
SKILL.md
READMESKILL.md - M04 Zero Cost
# Zero-Cost Abstraction > **Layer 1: Language Mechanics** ## Core Question **Do we need compile-time or runtime polymorphism?** Before choosing between generics and trait objects: - Is the type known at compile time? - Is a heterogeneous collection needed? - What's the performance priority? --- ## Error → Design Question | Error | Don't Just Say | Ask Instead | |-------|----------------|-------------| | E0277 | "Add trait bound" | Is this abstraction at the right level? | | E0308 | "Fix the type" | Should types be unified or distinct? | | E0599 | "Import the trait" | Is the trait the right abstraction? | | E0038 | "Make object-safe" | Do we really need dynamic dispatch? | --- ## Thinking Prompt Before adding trait bounds: 1. **What abstraction is needed?** - Same behavior, different types → trait - Different behavior, same type → enum - No abstraction needed → concrete type 2. **When is type known?** - Compile time → generics (static dispatch) - Runtime → trait objects (dynamic dispatch) 3. **What's the trade-off priority?** - Performance → generics - Compile time → trait objects - Flexibility → depends --- ## Trace Up ↑ When type system fights back: ``` E0277 (trait bound not satisfied) ↑ Ask: Is the abstraction level correct? ↑ Check: m09-domain (what behavior is being abstracted?) ↑ Check: m05-type-driven (should use newtype?) ``` | Persistent Error | Trace To | Question | |-----------------|----------|----------| | Complex trait bounds | m09-domain | Is the abstraction right? | | Object safety issues | m05-type-driven | Can typestate help? | | Type explosion | m10-performance | Accept dyn overhead? | --- ## Trace Down ↓ From design to implementation: ``` "Need to abstract over types with same behavior" ↓ Types known at compile time → impl Trait or generics ↓ Types determined at runtime → dyn Trait "Need collection of different types" ↓ Closed set → enum ↓ Open set → Vec<Box<dyn Trait>> "Need to return different types" ↓ Same type → impl Trait ↓ Different types → Box<dyn Trait> ``` --- ## Quick Reference | Pattern | Dispatch | Code Size | Runtime Cost | |---------|----------|-----------|--------------| | `fn foo<T: Trait>()` | Static | +bloat | Zero | | `fn foo(x: &dyn Trait)` | Dynamic | Minimal | vtable lookup | | `impl Trait` return | Static | +bloat | Zero | | `Box<dyn Trait>` | Dynamic | Minimal | Allocation + vtable | ## Syntax Comparison ```rust // Static dispatch - type known at compile time fn process(x: impl Display) { } // argument position fn process<T: Display>(x: T) { } // explicit generic fn get() -> impl Display { } // return position // Dynamic dispatch - type determined at runtime fn process(x: &dyn Display) { } // reference fn process(x: Box<dyn Display>) { } // owned ``` ## Error Code Reference | Error | Cause | Quick Fix | |-------|-------|-----------| | E0277 | Type doesn't impl trait | Add impl or change bound | | E0308 | Type mismatch | Check generic params | | E0599 | No method found | Import trait with `use` | | E0038 | Trait not object-safe | Use generics or redesign | --- ## Decision Guide | Scenario | Choose | Why | |----------|--------|-----| | Performance critical | Generics | Zero runtime cost | | Heterogeneous collection | `dyn Trait` | Different types at runtime | | Plugin architecture | `dyn Trait` | Unknown types at compile | | Reduce compile time | `dyn Trait` | Less monomorphization | | Small, known type set | `enum` | No indirection | --- ## Object Safety A trait is object-safe if it: - Doesn't have `Self: Sized` bound - Doesn't return `Self` - Doesn't have generic method