All Rust templates

Modern Rust Rules

Idiomatic Rust: ownership, error handling with ?, traits, modules, cargo.

DevZone Tools2,520 copiesUpdated Apr 13, 2026Rust
# CLAUDE.md — Modern Rust

## Edition & toolchain

- Use the latest stable Rust edition. Set `edition = "2024"` (or current) in `Cargo.toml`.
- Pin the toolchain in `rust-toolchain.toml` for reproducibility.
- `cargo fmt`, `cargo clippy --all-targets --all-features -- -D warnings` in CI. No exceptions.

## Project layout

```
Cargo.toml
src/
  lib.rs           # public API
  main.rs          # binary, if any
  error.rs         # crate-level errors
  domain/
  infra/
tests/             # integration tests
benches/
```

- For multi-crate projects, use a workspace with members. Keep crates focused — one responsibility each.

## Ownership & borrowing

- Default to **owned** types in function signatures (`String`, `Vec<T>`) when the function takes ownership; **slices** (`&str`, `&[T]`) when it borrows. Don't take `&String` or `&Vec<T>`.
- Prefer iterators over indexed loops. They're easier for the borrow checker and the compiler.
- Lifetimes: elide when possible. Name them only when the compiler asks for it.

## Errors

- Two error styles for two contexts:
  - **Library**: a typed error enum with `thiserror`. Each variant tells the caller exactly what went wrong.
  - **Application**: `anyhow::Result<T>` for "I just want to bubble errors up with context".
- Add context with `.context(...)` (anyhow) or `.map_err(|e| MyError::Foo { source: e })` (thiserror).
- Use `?` for propagation. Don't `unwrap` or `expect` outside tests and `main` — even `main` should bubble errors with `Result`.

## Structs & traits

- Derive aggressively when it makes sense: `Debug`, `Clone`, `PartialEq`, `Eq`, `Hash`. Don't derive `Default` blindly — it constructs an "empty" value that may not be valid.
- Builder pattern for structs with many optional fields. Use `bon` or `derive_builder` to avoid boilerplate.
- Don't write trait objects (`Box<dyn Trait>`) when generics work. Reach for `dyn` only when you genuinely need heterogeneous types.

## Modules

- One module per file. The directory pattern (`mod.rs` → `module.rs` + folder) is preferred over the older single-file form for anything beyond trivial.
- `pub` is opt-in. Most items stay private.
- Re-export via `pub use` to flatten the public API. Consumers shouldn't have to know your internal layout.

## Cargo features

- Use features for optional functionality, not for two ways of doing the same thing.
- Document features in `Cargo.toml` and `README`.
- `default-features = false` when consuming a dep — explicit > implicit.

## Performance

- Profile with `cargo flamegraph` or `samply` before optimizing.
- Avoid unnecessary allocations in hot loops. Reach for `&str` over `String` when you can.
- `cargo bench` with **criterion** for serious benchmarks.

## Don't

- Don't use `unwrap()` outside tests, examples, and prototypes. Even there, prefer `expect("explanation")`.
- Don't use `Rc<RefCell<T>>` to "fix" a borrow-checker problem. Redesign the ownership.
- Don't add `unsafe` without a comment explaining the safety invariant.
- Don't write `.clone()` to silence a borrow error. Understand what's actually moving.

Other Rust templates