| name | rust-learner |
| description | Rust-specific learning guidance for the nginx-lite project. Loaded alongside the generic coding-sprints skill to provide language-specific idiom checks, recommended reads per concept, and progressive constraints. Use when reviewing Rust code in this project, answering Rust-specific questions, or suggesting reads for Rust concepts.
|
Rust Learner — nginx-lite
Rust-specific guidance for this learning project. Works alongside the coding-sprints skill.
User Profile
- Background: Software engineer, knows Go well, TypeScript, Python
- Rust level: Understands ownership conceptually, never built anything real
- Gaps: idioms, lifetimes in practice, async patterns, trait design, error handling patterns
- Strengths: systems thinking, concurrency mental models (from Go), strong design sense
Idiom Checks (apply during review mode)
When reviewing code, watch for these common "coming from other languages" patterns:
| Pattern | Issue | Idiomatic Alternative |
|---|
.clone() everywhere | Avoiding borrow checker instead of understanding it | Borrow, reference, or restructure ownership |
unwrap() in non-test code | Go's if err != nil instinct but wrong in Rust | ? operator, map_err, unwrap_or_else |
Box<dyn Trait> by default | Java/Go interface instinct | Generics first, dyn only when needed |
Huge structs with all pub fields | Go struct habits | Private fields + constructor + methods |
| Manual loops over iterators | Imperative habits | .map(), .filter(), .collect() chains |
String in struct fields when &str would work | Not thinking about lifetimes | Consider Cow<'_, str> or proper lifetime |
Giant match statements | Not using combinators | .map(), .and_then(), .unwrap_or() on Option/Result |
Recommended Reads by Concept
Ownership & Borrowing
Error Handling
Async/Await
Traits & Generics
Concurrency
Modules & Project Structure
Progressive Constraints
Suggest these constraints as the user advances through sprints:
| Sprint | Constraint |
|---|
| 1-2 | No constraint. Learn the basics. clone() is fine. |
| 3-4 | Minimize .clone() — ask "can this borrow instead?" |
| 5-6 | No unwrap() outside tests. All errors handled with ?. |
| 7-8 | All public types must be Send + Sync. Think about thread safety. |
| 9-10 | No Box<dyn> unless you can explain why generics won't work here. |
Key Differences from Go (reference for explanations)
| Go | Rust | Why |
|---|
interface{} | dyn Any / generics | Rust prefers compile-time polymorphism |
| Goroutines are cheap | tokio::spawn has overhead | Be intentional about task boundaries |
error interface | Result<T, E> with typed errors | Compiler enforces handling |
| GC handles memory | Ownership system | No GC, no runtime cost |
defer | Drop trait / RAII | Automatic, tied to scope, not function exit |
| Channels for everything | Channels OR shared state | Rust makes both safe |
struct with exported fields | struct with private fields + impl | Encapsulation by default |