
M15 Anti Pattern
Recognize and fix common Rust ownership, allocation, and error-handling mistakes while writing or reviewing code.
Overview
m15-anti-pattern is an agent skill most often used in Build (also Ship review) that catalogs common Rust mistakes and idiomatic fixes for ownership and error handling.
Install
npx skills add https://github.com/actionbook/rust-skills --skill m15-anti-patternWhat is this skill?
- Ownership section covers clone-everywhere, unnecessary `Box`, and holding references too long
- Shows side-by-side anti-pattern vs idiomatic borrow or copy fixes
- Error-handling section contrasts `unwrap` chains with `?` propagation
- Structured as quick reference snippets for agent-assisted refactors
- Fits pre-review self-checks before opening a PR on Rust crates
Adoption & trust: 938 installs on skills.sh; 1.2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Rust code compiles only after excessive clones and `unwrap`, or you keep fighting borrow errors without knowing the idiomatic pattern.
Who is it for?
Indie builders iterating on Rust backends or CLIs who want fast pattern guidance during coding or PR prep.
Skip if: Greenfield Rust learners who need a full language course, or teams that only need automated lint rules without explanatory context.
When should I use this skill?
User is writing or reviewing Rust and hits recurring ownership clones, boxed returns, long-lived borrows, or error handling with `unwrap`.
What do I get? / Deliverables
You refactor toward borrows, slimmer types, and propagated `Result` errors so modules are safer to extend and review.
- Refactored snippet guidance
- Anti-pattern vs idiomatic comparison for cited code
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Primary shelf is build/backend because the content targets implementation patterns in Rust services, CLIs, and systems code. Backend subphase matches systems-style Rust where borrow checker friction and `Result` propagation matter most day to day.
Where it fits
Rewrite a hot path that clones `Vec` on every iteration to use shared references instead.
Harden a TOML or HTTP client loader so parse and I/O errors return `Result` instead of panicking.
Scan a PR for `unwrap` in file and config loading before release.
How it compares
Skill-backed pattern reference, not a substitute for `cargo clippy`, `miri`, or formal unsafe audits.
Common Questions / FAQ
Who is m15-anti-pattern for?
Solo developers writing or reviewing Rust who want the agent to flag habitual anti-patterns with concrete rewrite examples.
When should I use m15-anti-pattern?
During build/backend implementation when rustc borrow errors recur; in ship/review before merge when you see `unwrap` in I/O paths; or when refactoring agent-generated Rust toward idiomatic ownership.
Is m15-anti-pattern safe to install?
It is documentation-only procedural knowledge with no extra network calls; confirm trust via the Security Audits panel on this Prism page.
SKILL.md
READMESKILL.md - M15 Anti Pattern
# Common Rust Anti-Patterns & Mistakes ## Ownership Anti-Patterns ### 1. Clone Everything ```rust // ANTI-PATTERN: clone to avoid borrow checker fn process(data: Vec<String>) { for item in data.clone() { // unnecessary clone println!("{}", item); } use_data(data); } // BETTER: borrow when you don't need ownership fn process(data: Vec<String>) { for item in &data { // borrow instead println!("{}", item); } use_data(data); } ``` ### 2. Unnecessary Box ```rust // ANTI-PATTERN: boxing everything fn get_value() -> Box<String> { Box::new(String::from("hello")) } // BETTER: return value directly fn get_value() -> String { String::from("hello") } ``` ### 3. Holding References Too Long ```rust // ANTI-PATTERN: borrow prevents mutation let mut data = vec![1, 2, 3]; let first = &data[0]; data.push(4); // ERROR: data is borrowed println!("{}", first); // BETTER: scope the borrow let mut data = vec![1, 2, 3]; let first = data[0]; // copy the value data.push(4); // OK println!("{}", first); ``` --- ## Error Handling Anti-Patterns ### 4. Unwrap Everywhere ```rust // ANTI-PATTERN: crashes on error fn process_file(path: &str) { let content = std::fs::read_to_string(path).unwrap(); let config: Config = toml::from_str(&content).unwrap(); } // BETTER: propagate errors fn process_file(path: &str) -> Result<Config, Error> { let content = std::fs::read_to_string(path)?; let config: Config = toml::from_str(&content)?; Ok(config) } ``` ### 5. Ignoring Errors ```rust // ANTI-PATTERN: silent failure let _ = file.write_all(data); // BETTER: handle or propagate file.write_all(data)?; // or at minimum, log the error if let Err(e) = file.write_all(data) { eprintln!("Warning: failed to write: {}", e); } ``` ### 6. Panic in Library Code ```rust // ANTI-PATTERN: library panics pub fn parse(input: &str) -> Data { if input.is_empty() { panic!("input cannot be empty"); } // ... } // BETTER: return Result pub fn parse(input: &str) -> Result<Data, ParseError> { if input.is_empty() { return Err(ParseError::EmptyInput); } // ... } ``` --- ## String Anti-Patterns ### 7. String Instead of &str ```rust // ANTI-PATTERN: forces allocation fn greet(name: String) { println!("Hello, {}", name); } greet("world".to_string()); // allocation // BETTER: accept &str fn greet(name: &str) { println!("Hello, {}", name); } greet("world"); // no allocation ``` ### 8. Format for Simple Concatenation ```rust // ANTI-PATTERN: format overhead let greeting = format!("{}{}", "Hello, ", name); // BETTER for simple cases: push_str let mut greeting = String::from("Hello, "); greeting.push_str(name); // Or use + for String + &str let greeting = String::from("Hello, ") + name; ``` ### 9. Repeated String Operations ```rust // ANTI-PATTERN: O(n²) allocations let mut result = String::new(); for word in words { result = result + word + " "; } // BETTER: join let result = words.join(" "); // Or with_capacity + push_str let mut result = String::with_capacity(total_len); for word in words { result.push_str(word); result.push(' '); } ``` --- ## Collection Anti-Patterns ### 10. Index Instead of Iterator ```rust // ANTI-PATTERN: bounds checking overhead for i in 0..vec.len() { process(vec[i]); } // BETTER: iterator for item in &vec { process(item); } ``` ### 11. Collect Then Iterate ```rust // ANTI-PATTERN: unnecessary allocation let filtered: Vec<_> = items.iter().filter(|x| x.valid).collect(); for item in filtered { process(item); } // BETTER: chain iterators for item in items.iter().filter(|x| x.valid) { process(item); } ``` ### 12. Wrong Collection Type ```rust // ANTI-PATTERN: Vec for frequent membership checks let allowed: Vec<&str> = vec!["a", "b", "c"]; if allowed.contains(&input) { ... } // O(n) // BETTER: HashSet for membership use std::collections::HashSet; let allowed: HashSet<&str> = ["a", "b",