Rust Core Toolchain Conventions
Edition and Toolchain
- Target Rust 2024 edition. MSRV is set by the most-constrained transitive dependency,
not the edition floor — pin it explicitly in
Cargo.toml(rust-version = "..."). - Gate every change on
cargo fmt --check,cargo clippy -- -D warnings, andcargo test. - Prefer
cargo nextest runfor faster, isolated test execution when available.
Ownership and Borrowing
- Borrow by default, own only when necessary. Accept
&str/&[T]in function signatures, notString/Vec<T>, unless the function must take ownership. - Return owned values; let callers borrow. Avoid returning references tied to locals.
- Reach for
Cow<'_, str>when a value is usually borrowed but occasionally owned. - Use
Rc/Arconly for genuine shared ownership; prefer passing references first. - Interior mutability:
Cell/RefCellfor single-threaded,Mutex/RwLock(underArc) for shared-state concurrency. Never hold a lock across an.await.
Error Handling
- Never
unwrap()/expect()/panic!in library code. ReturnResult<T, E>. - Libraries: define a typed error enum with
thiserror. Applications:anyhow::Resultwith.context(...)to add provenance at each boundary. - Use the
?operator for propagation; convert errors withFrom/#[from]. - Reserve
panic!for truly unreachable invariants, and document why.
Async with tokio
- Use
#[tokio::main](or an explicit runtime) andasync/.awaitfor I/O-bound work. - Spawn concurrent work with
tokio::spawn; join withtokio::join!ortry_join!. - Apply explicit timeouts via
tokio::time::timeouton all external calls. - Offload CPU-bound work with
tokio::task::spawn_blocking— never block the runtime. - Hold no
std::synclock across an.await; usetokio::syncprimitives instead.
Project Structure and Idioms
- One responsibility per module; expose a curated public API via
pubinlib.rs. - Derive
Debug, andClone/PartialEq/Eqwhere cheap and meaningful. - Model state with enums + exhaustive
match; avoid boolean-flag soup. - Prefer iterator chains over manual index loops; they are clearer and often faster.
- Use newtypes (
struct UserId(u64)) to make illegal states unrepresentable. - Write doctests for public functions; they double as runnable documentation.