一键导入
rust-coding
Rust coding conventions expert covering naming, formatting, comments, clippy, rustfmt, lints, code style, best practices, and idiomatic patterns.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Rust coding conventions expert covering naming, formatting, comments, clippy, rustfmt, lints, code style, best practices, and idiomatic patterns.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Actor model expert covering message passing, state isolation, supervision trees, deadlock prevention, fault tolerance, Actix framework, and Erlang-style concurrency patterns.
Rust anti-patterns and common mistakes expert. Handles code review issues with clone abuse, unwrap in production, String misuse, index loops, and refactoring guidance.
Advanced async patterns expert covering Stream implementation, zero-copy buffers, tokio::spawn lifetimes, plugin system scheduling, tonic streaming, and async lifetime management.
Advanced async patterns expert. Handles Stream processing, backpressure control, select/join operations, cancellation, Future trait implementation, and async runtime optimization.
Authentication and authorization expert covering JWT, API keys, OAuth, RBAC, password hashing, distributed token storage, and session management patterns.
Caching and distributed storage expert covering Redis, connection pools, TTL strategies, cache patterns (Cache-Aside, Write-Through), invalidation, and performance optimization.
| 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"]} |
| 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 |
// Variables and functions: snake_case
let max_connections = 100;
fn process_data() { ... }
// Types and traits: CamelCase
struct UserSession;
trait Cacheable {}
// Constants: SCREAMING_SNAKE_CASE
const MAX_CONNECTIONS: usize = 100;
static CONFIG: once_cell::sync::Lazy<Config> = ...
impl Buffer {
// as_ - cheap, view conversion
pub fn as_slice(&self) -> &[u8] {
&self.data
}
// to_ - expensive, allocating conversion
pub fn to_vec(&self) -> Vec<u8> {
self.data.clone()
}
// into_ - consuming, ownership transfer
pub fn into_vec(self) -> Vec<u8> {
self.data
}
}
// ✅ Domain semantics with newtypes
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)
}
}
}
// ✅ Good: propagate errors
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)
}
// ❌ Avoid: panic in library code
fn read_config() -> Config {
std::fs::read_to_string("config.toml").unwrap() // panic!
}
// ✅ Use expect when invariant guaranteed
fn get_user(&self) -> &User {
self.user.as_ref()
.expect("user always initialized in constructor")
}
// ✅ Accept &str in APIs
fn greet(name: &str) {
println!("Hello, {}", name);
}
// ✅ Use Cow when might need owned
use std::borrow::Cow;
fn process(input: &str) -> Cow<str> {
if input.contains("special") {
Cow::Owned(input.replace("special", "normal"))
} else {
Cow::Borrowed(input)
}
}
// ✅ Pre-allocate when size known
let mut s = String::with_capacity(100);
| 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] |
| 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 |
| Rule | Description |
|---|---|
Use ? to propagate | Don't use try!() macro |
expect() over unwrap() | When value guaranteed |
Use assert! for invariants | At function entry |
| Rule | Description |
|---|---|
| Meaningful lifetime names | 'src, 'ctx not just 'a |
RefCell use try_borrow | Avoid panics |
| Use shadowing for conversions | let x = x.parse()? |
| Rule | Description |
|---|---|
| Define lock ordering | Prevent deadlocks |
| Atomics for primitives | Not Mutex<bool> |
| Choose memory ordering carefully | Relaxed/Acquire/Release/SeqCst |
| Rule | Description |
|---|---|
| CPU-bound → sync | Async for I/O |
| Don't hold locks across await | Use scoped guards |
| Rule | Description |
|---|---|
| Avoid macros (unless necessary) | Prefer functions/generics |
| Macro input like Rust | Readability first |
| 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 |
[package]
edition = "2024"
rust-version = "1.85"
[lints.rust]
unsafe_code = "warn"
[lints.clippy]
all = "warn"
pedantic = "warn"
| 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 |
# Use default config
rustfmt src/lib.rs
# Check formatting
rustfmt --check src/lib.rs
# Config file: .rustfmt.toml
max_width = 100
tab_spaces = 4
edition = "2024"
/// Module documentation
//! This module handles user authentication...
/// Struct documentation
///
/// # Examples
/// ```
/// let user = User::new("name");
/// ```
pub struct User { ... }
/// Method documentation
///
/// # Arguments
///
/// * `name` - User name
///
/// # Returns
///
/// Initialized user instance
///
/// # Panics
///
/// Panics when name is empty
pub fn new(name: &str) -> Self { ... }
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()
# Run rustfmt
cargo fmt
# Check formatting in CI
cargo fmt --check
# Fix clippy warnings
cargo clippy --fix
Check:
→ No unnecessary clone()
→ Use ? not unwrap()
→ &str in function parameters
→ Iterator methods not index loops
→ Meaningful error types
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)]
When reviewing code:
? instead of unwrap()clone()unsafe blocks have SAFETY commentscargo clippycargo fmtget_ prefix on accessor methods&str when possible# Format check
cargo fmt --check
# Lint check
cargo clippy -- -D warnings
# Documentation check
cargo doc --no-deps --open
# Run tests
cargo test
# Check naming conventions
cargo clippy -- -W clippy::wrong_self_convention
Symptom: Clippy warning wrong_self_convention
// ❌ Bad: unnecessary get_ prefix
impl User {
fn get_name(&self) -> &str { &self.name }
}
// ✅ Good: direct accessor
impl User {
fn name(&self) -> &str { &self.name }
}
Symptom: Unnecessary allocations
// ❌ Bad: forces allocation
fn greet(name: String) {
println!("Hello, {}", name);
}
// ✅ Good: accepts borrowed or owned
fn greet(name: &str) {
println!("Hello, {}", name);
}
// Both work now:
greet("Alice"); // &str
greet(&owned_string); // &String → &str
Symptom: Less idiomatic, error-prone
// ❌ Bad: manual indexing
for i in 0..items.len() {
println!("{}: {}", i, items[i]);
}
// ✅ Good: iterator
for item in &items {
println!("{}", item);
}
// ✅ Good: with index
for (i, item) in items.iter().enumerate() {
println!("{}: {}", i, item);
}