Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Rust coding best practices for idiomatic, efficient, and maintainable code. Use when writing Rust code, reviewing code, or learning Rust patterns.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 73% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 165% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 64% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 96% | 0% |
Guidelines for writing idiomatic, efficient, and maintainable Rust code.
Use thiserror
rustuse thiserror::Error; #[derive(Error, Debug)] pub enum ConfigError { #[error("Failed to read config: {0}")] Io(#[from] std::io::Error), #[error("Failed to parse config: {0}")] Parse(#[from] toml::de::Error), #[error("Invalid configuration: {message}")] Invalid { message: String }, }
.unwrap()rust// BAD let value = map.get("key").unwrap(); // GOOD let value = map.get("key").ok_or_else(|| Error::MissingKey("key"))?; // GOOD (when None is truly impossible) let value = map.get("key").expect("key always present after init");
rust// BAD - unnecessary clone fn process(data: String) { ... } process(my_string.clone()); // GOOD - borrow when possible fn process(data: &str) { ... } process(&my_string);
Cow for Flexible Ownershiprustuse std::borrow::Cow; fn process(data: Cow<'_, str>) -> Cow<'_, str> { if data.contains("bad") { Cow::Owned(data.replace("bad", "good")) } else { data // No allocation if unchanged } }
rust// GOOD - clear ownership impl User { pub fn new(name: impl Into<String>) -> Self { Self { name: name.into() } } }
rust#[derive(Default)] pub struct ServerBuilder { host: Option<String>, port: Option<u16>, timeout: Option<Duration>, } impl ServerBuilder { pub fn host(mut self, host: impl Into<String>) -> Self { self.host = Some(host.into()); self } pub fn port(mut self, port: u16) -> Self { self.port = Some(port); self } pub fn build(self) -> Result<Server, ConfigError> { Ok(Server { host: self.host.unwrap_or_else(|| "localhost".into()), port: self.port.ok_or(ConfigError::MissingPort)?, timeout: self.timeout.unwrap_or(Duration::from_secs(30)), }) } }
rust// BAD - easy to mix up fn transfer(from: i64, to: i64, amount: i64) { ... } // GOOD - compile-time safety pub struct AccountId(i64); pub struct Amount(i64); fn transfer(from: AccountId, to: AccountId, amount: Amount) { ... }
#[must_use] for Important Returnsrust#[must_use] pub fn validate(&self) -> Result<(), ValidationError> { // ... }
rust// BAD let mut results = Vec::new(); for item in items { if item.is_valid() { results.push(item.transform()); } } // GOOD let results: Vec<_> = items .into_iter() .filter(|item| item.is_valid()) .map(|item| item.transform()) .collect();
collect() Type Inferencerust// Collect into Vec let vec: Vec<_> = iter.collect(); // Collect into HashMap let map: HashMap<_, _> = iter.collect(); // Collect Results let results: Result<Vec<_>, _> = iter.collect();
tokio for Async Runtimerust#[tokio::main] async fn main() -> Result<()> { let result = fetch_data().await?; Ok(()) }
rust// BAD - blocks the runtime async fn bad() { std::thread::sleep(Duration::from_secs(1)); } // GOOD - async sleep async fn good() { tokio::time::sleep(Duration::from_secs(1)).await; } // GOOD - spawn blocking for CPU-intensive work async fn compute() -> i32 { tokio::task::spawn_blocking(|| expensive_computation()).await.unwrap() }
rust#[cfg(test)] mod tests { use super::*; #[test] fn test_basic() { assert_eq!(add(1, 2), 3); } #[test] fn test_edge_case() { assert!(validate("").is_err()); } }
tests/rust// tests/integration_test.rs use my_crate::public_api; #[test] fn test_full_workflow() { let result = public_api::process("input"); assert!(result.is_ok()); }
assert! Macros Effectivelyrustassert!(condition); assert_eq!(left, right); assert_ne!(left, right); assert!(result.is_ok()); assert!(result.is_err()); assert_matches!(value, Pattern::Variant { .. });
rust// BAD - allocates even if not needed fn maybe_string() -> String { String::from("default") } // GOOD - return static str when possible fn maybe_string() -> &'static str { "default" }
Vec::with_capacity for Known Sizesrust// BAD - multiple reallocations let mut vec = Vec::new(); for i in 0..1000 { vec.push(i); } // GOOD - single allocation let mut vec = Vec::with_capacity(1000); for i in 0..1000 { vec.push(i); }
rust/// BAD let v = tokio::net::TcpStream::connect("localhost:8080"); /// GOOD use tokio::net::TcpStream; let v = TcpStream::connect("localhost:8080");
bashcargo build --release cargo flamegraph # requires cargo-flamegraph
rust// src/lib.rs pub mod config; pub mod client; pub mod error; // Re-export public API pub use config::Config; pub use client::Client; pub use error::Error;
pub(crate) for Internal APIsrust// Public to crate, not external users pub(crate) fn internal_helper() { ... }
rust/// Creates a new client with the given configuration. /// /// # Arguments /// /// * `config` - The client configuration /// /// # Errors /// /// Returns an error if the configuration is invalid. /// /// # Examples /// /// ``` /// let client = Client::new(Config::default())?; /// ``` pub fn new(config: Config) -> Result<Self> { // ... }
| Anti-Pattern | Better Approach | |--------------|-----------------| | .unwrap() everywhere | Use ? operator | | clone() to satisfy borrow checker | Restructure ownership | | String parameters | Use &str or impl Into<String> | | Boolean parameters | Use enums | | Long function bodies | Extract to smaller functions | | Deep nesting | Use early returns | | Magic numbers | Use named constants |
bash# Quality gates cargo fmt -- --check && cargo clippy -- -D warnings && cargo test # Common cargo commands cargo check # Fast syntax/type check cargo build # Debug build cargo build --release # Release build cargo nextest run # Run tests cargo doc --open # Generate and view docs cargo clippy --fix # Auto-fix lint issues
Other measured skills in the registry, with their headline benchmark lift.