| name | rust-coding |
| description | Rust coding conventions expert covering naming, formatting, comments, clippy, rustfmt, lints, code style, best practices, and idiomatic patterns. |
| metadata | {"triggers":["coding convention","naming","formatting","clippy","rustfmt","lint","code style","best practice","idiomatic","code review"]} |
Naming Conventions (Rust-Specific)
| Rule | Correct | Incorrect |
|---|
No get_ prefix for methods | fn name(&self) | fn get_name(&self) |
| Iterator methods | iter() / iter_mut() / into_iter() | get_iter() |
| Conversion naming | as_ (cheap), to_ (expensive), into_ (ownership) | Mixed usage |
static variables uppercase | static CONFIG: Config | static config: Config |
const variables | const BUFFER_SIZE: usize = 1024 | No restriction |
General Naming
let max_connections = 100;
fn process_data() { ... }
struct UserSession;
trait Cacheable {}
const MAX_CONNECTIONS: usize = 100;
static CONFIG: once_cell::sync::Lazy<Config> = ...
Solution Patterns
Pattern 1: Conversion Methods
impl Buffer {
pub fn as_slice(&self) -> &[u8] {
&self.data
}
pub fn to_vec(&self) -> Vec<u8> {
self.data.clone()
}
pub fn into_vec(self) -> Vec<u8> {
self.data
}
}
Pattern 2: Newtype Pattern
struct Email(String);
struct UserId(u64);
struct Meters(f64);
impl Email {
pub fn new(s: impl Into<String>) -> Result<Self, EmailError> {
let email = s.into();
if email.contains('@') {
Ok(Self(email))
} else {
Err(EmailError::Invalid)
}
}
}
Pattern 3: Error Handling
fn read_config() -> Result<Config, ConfigError> {
let content = std::fs::read_to_string("config.toml")
.map_err(ConfigError::from)?;
toml::from_str(&content)
.map_err(ConfigError::Parse)
}
fn read_config() -> Config {
std::fs::read_to_string("config.toml").unwrap()
}
fn get_user(&self) -> &User {
self.user.as_ref()
.expect("user always initialized in constructor")
}
Pattern 4: String Handling
fn greet(name: &str) {
println!("Hello, {}", name);
}
use std::borrow::Cow;
fn process(input: &str) -> Cow<str> {
if input.contains("special") {
Cow::Owned(input.replace("special", "normal"))
} else {
Cow::Borrowed(input)
}
}
let mut s = String::with_capacity(100);
Data Type Guidelines
| Rule | Description | Example |
|---|
| Use newtype | Domain semantics | struct Email(String) |
| Use slice patterns | Pattern matching | if let [first, .., last] = slice |
| Pre-allocate | Avoid reallocations | Vec::with_capacity() |
| Avoid Vec abuse | Fixed size → array | let arr: [u8; 256] |
String Guidelines
| Rule | Description |
|---|
ASCII data use bytes() | s.bytes() faster than s.chars() |
Might modify → Cow<str> | Borrow or owned |
Use format! for concat | Better than + operator |
Avoid nested contains() | O(n*m) complexity |
Error Handling Guidelines
| Rule | Description |
|---|
Use ? to propagate | Don't use try!() macro |
expect() over unwrap() | When value guaranteed |
Use assert! for invariants | At function entry |
Memory and Lifetimes
| Rule | Description |
|---|
| Meaningful lifetime names | 'src, 'ctx not just 'a |
RefCell use try_borrow | Avoid panics |
| Use shadowing for conversions | let x = x.parse()? |
Concurrency Guidelines
| Rule | Description |
|---|
| Define lock ordering | Prevent deadlocks |
| Atomics for primitives | Not Mutex<bool> |
| Choose memory ordering carefully | Relaxed/Acquire/Release/SeqCst |
Async Guidelines
| Rule | Description |
|---|
| CPU-bound → sync | Async for I/O |
| Don't hold locks across await | Use scoped guards |
Macro Guidelines
| Rule | Description |
|---|
| Avoid macros (unless necessary) | Prefer functions/generics |
| Macro input like Rust | Readability first |
Deprecated Patterns → Modern
| Deprecated | Modern | Version |
|---|
lazy_static! | std::sync::OnceLock | 1.70 |
once_cell::Lazy | std::sync::LazyLock | 1.80 |
std::sync::mpsc | crossbeam::channel | - |
std::sync::Mutex | parking_lot::Mutex | - |
failure/error-chain | thiserror/anyhow | - |
try!() | ? operator | 2018 |
Clippy Configuration
[package]
edition = "2024"
rust-version = "1.85"
[lints.rust]
unsafe_code = "warn"
[lints.clippy]
all = "warn"
pedantic = "warn"
Common Clippy Lints
| Lint | Description |
|---|
clippy::all | Enable all warnings |
clippy::pedantic | Stricter checks |
clippy::unwrap_used | Avoid unwrap |
clippy::expect_used | Prefer expect |
clippy::clone_on_ref_ptr | Avoid cloning Arc |
Formatting (rustfmt)
rustfmt src/lib.rs
rustfmt --check src/lib.rs
max_width = 100
tab_spaces = 4
edition = "2024"
Documentation Guidelines
pub struct User { ... }
pub fn new(name: &str) -> Self { ... }
Workflow
Step 1: Name Things Properly
Choosing a name?
→ Function/variable? snake_case
→ Type/trait? CamelCase
→ Constant? SCREAMING_SNAKE_CASE
→ Conversion method?
- Cheap view? as_foo()
- Expensive? to_foo()
- Consuming? into_foo()
Step 2: Format Code
cargo fmt
cargo fmt --check
cargo clippy --fix
Step 3: Review Idioms
Check:
→ No unnecessary clone()
→ Use ? not unwrap()
→ &str in function parameters
→ Iterator methods not index loops
→ Meaningful error types
Quick Reference
Naming: snake_case (fn/var), CamelCase (type), SCREAMING_SNAKE_CASE (const)
Format: rustfmt (just use it)
Docs: /// for public items, //! for module docs
Lint: #![warn(clippy::all)]
Review Checklist
When reviewing code:
Verification Commands
cargo fmt --check
cargo clippy -- -D warnings
cargo doc --no-deps --open
cargo test
cargo clippy -- -W clippy::wrong_self_convention
Common Pitfalls
1. Wrong Method Naming
Symptom: Clippy warning wrong_self_convention
impl User {
fn get_name(&self) -> &str { &self.name }
}
impl User {
fn name(&self) -> &str { &self.name }
}
2. String Type Misuse
Symptom: Unnecessary allocations
fn greet(name: String) {
println!("Hello, {}", name);
}
fn greet(name: &str) {
println!("Hello, {}", name);
}
greet("Alice");
greet(&owned_string);
3. Index Loops
Symptom: Less idiomatic, error-prone
for i in 0..items.len() {
println!("{}: {}", i, items[i]);
}
for item in &items {
println!("{}", item);
}
for (i, item) in items.iter().enumerate() {
println!("{}: {}", i, item);
}
Related Skills
- rust-anti-pattern - What not to do
- rust-error - Error handling patterns
- rust-performance - Performance idioms
- rust-async - Async conventions
- rust-unsafe - SAFETY comment style
Localized Reference