Rust Development
Master Rust development using a layer-based "meta-cognition" framework. Use whenever writing Rust code, resolving borrow checker errors (E0382, E0596), designing ownership patterns (Arc, Mutex), or performing crate selection.
Rust Development & Meta-Cognition
When solving Rust problems, do not immediately write code. Trace through the cognitive layers first to understand the data's lifecycle, ownership, and constraints.
🧠 1. The Meta-Cognition Framework (Before You Code)
Layer 1: Domain Constraints (WHY)
What is the system trying to achieve?
- Web Service: Concurrent, async, low-latency (Requires
axum,tokio,Arc<Mutex<T>>). - CLI Tool: Fast startup, zero overhead, clean exit codes (Requires
clap,anyhow, strict error formatting). - Embedded / Systems: No heap allocation (Requires
no_std, specific hardware limitations).
Layer 2: Design Choices & Ownership (WHAT)
Ask the core question: Who should own this data?
- Single owner, strictly unique: Direct value or
Box<T>. - Single thread, multiple owners:
Rc<T>(useRefCell<T>for mutation). - Multi-thread, multiple owners:
Arc<T>(useMutex<T>orRwLock<T>for mutation).
Why does it need to mutate? Avoid slapping mut everywhere. Prefer returning new values or using tight, scoped mutability.
Layer 3: Language Mechanics (HOW)
Use the compiler's strictness as a tool, not an obstacle.
- Implement standard traits:
Drop,Clone,Default,Display,From,TryFrom. - Avoid
unwrap()orexpect()in production logic. Propagate errors natively via?andResult.
🏗️ 2. Core Ecosystem Defaults
When selecting crates or recommending tools, stick to these canonical community standards:
- Async Runtime:
tokio(I/O bound) orrayon(CPU bound data-parallelism) - Web / API Server:
axum(built on tokio/hyper) - Serialization/Deserialization:
serdeandserde_json - Error Handling:
thiserror(for libraries),anyhoworcolor-eyre(for binaries) - Command Line Parsing:
clap - Logging & Telemetry:
tracingandtracing-subscriber - HTTP Client:
reqwest
🛡️ 3. Solving Borrow Checker Errors
When debugging compiler errors, trace up from the syntax error to the fundamental design choice.
- E0382 (Use of moved value):
- Symptom: You are trying to use a value after it was consumed.
- Resolve: Does the function actually need ownership? Borrow it instead (
&T),clone()it if lightweight, or wrap inArc<T>if access needs to be shared across threads.
- E0596 (Cannot borrow as mutable):
- Symptom: You are mutating something behind an immutable reference
&T. - Resolve: Change the signature to
&mut T, or if you must have an immutable interface, use interior mutability (CellorMutex).
- Symptom: You are mutating something behind an immutable reference
- E0499 (Cannot borrow multiple times):
- Symptom: Alive mutable references colliding.
- Resolve: Restructure the function to limit the reference's scope
{}, or avoid holding mutable borrows acrossawaitpoints.
⚡ 4. High-Integrity Code Patterns
- Avoid Panic-Driven Development:
clone()is an acceptable escape hatch during prototyping, but do not scatter it throughout the code. Revisit the lifetime boundaries as soon as it works. - The Newtype Pattern: Use tuple structs to prevent invalid state.
struct UserId(u64);avoids mixing it up withstruct OrderId(u64);. - Exhaustive Matching: Always use
matchoverif letwhen handling Enums or State Machines. The compiler will notify you when a new variant is added, preventing silent bugs. - Data-Oriented Modeling: Prefer small, flat structs that compose over deep, object-oriented inheritance hierarchies.
🛠️ 5. Standard Commands
- Run Application:
cargo run - Linting / Idioms:
cargo clippy -- -D warnings - Formatting:
cargo fmt - Testing:
cargo test
Agent Directive: When writing or editing Rust code, always invoke cargo clippy and cargo test dynamically to validate your implementations before concluding your task.