# Rust API Guidelines — Claude Code rules You are designing a public Rust crate / library API. Follow the official Rust API Guidelines. The checklist codes (C-CASE, C-COMMON-TRAITS, …) are the source of truth; the rules below distill them. ## Naming (RFC 430) - `UpperCamelCase` for types, traits, enum variants, and type parameters. Treat acronyms as one word: `Uuid`, not `UUID`. - `snake_case` for modules, functions, methods, locals, and macros (`!`). - `SCREAMING_SNAKE_CASE` for constants and statics. - Lifetimes are short and lowercase: `'a`, `'de`, `'src`. - Getters drop the `get_` prefix: `fn first(&self)`, not `get_first`. Reserve `get` for the single obvious accessor (e.g. `Cell::get`). (C-GETTER) - Conversion methods follow cost + ownership: `as_*` (free, borrow→borrow), `to_*` (expensive, borrow→owned), `into_*` (consuming, owned→owned). (C-CONV) - Iterator-producing methods are `iter` / `iter_mut` / `into_iter`, returning types named `Iter` / `IterMut` / `IntoIter`. (C-ITER, C-ITER-TY) - Keep a consistent word order matching std (e.g. `ParseIntError`). (C-WORD-ORDER) - Cargo feature names have no placeholder words: use `std`, not `use-std`; crate names avoid `-rs` / `-rust` suffixes. (C-FEATURE) ## Common traits & interop - Eagerly derive the standard traits when valid: `Debug`, `Clone`, `Copy`, `PartialEq`/`Eq`, `PartialOrd`/`Ord`, `Hash`, `Default`; implement `Display` where a human-facing form exists. Orphan rules mean downstream crates cannot add these later, so do it here. (C-COMMON-TRAITS) - Every public type implements `Debug`, and its output is non-empty. (C-DEBUG) - Conversions go through `From`, `TryFrom`, `AsRef`, `AsMut`. Never hand-write `Into` / `TryInto` — they come free via blanket impls. (C-CONV-TRAITS) - Collections implement `FromIterator` and `Extend`. (C-COLLECT) - Gate `serde::Serialize` / `Deserialize` behind a `serde` feature. (C-SERDE) - Keep types `Send + Sync` wherever the compiler allows. (C-SEND-SYNC) - Generic I/O takes `R: Read` / `W: Write` by value (callers pass `&mut`). (C-RW-VALUE) ## Error types - Public error types implement `std::error::Error` and are `Send + Sync + 'static` with useful `Debug` and `Display`. (C-GOOD-ERR) - Document failure modes: `# Errors` for `Result`-returning fns, `# Panics` for panics, `# Safety` for `unsafe` fns. (C-FAILURE) - Destructors never fail or block: `Drop` is infallible (a panic in `Drop` during unwinding aborts). Expose a separate `close()` / `flush()` returning `Result` for fallible teardown. (C-DTOR-FAIL, C-DTOR-BLOCK) ## Type safety - Use newtypes to give distinct static meaning to like-shaped values (`Miles(f64)` vs `Kilometers(f64)`). (C-NEWTYPE) - Convey intent through dedicated types/enums, not bare `bool` or `Option` arguments. (C-CUSTOM-TYPE) - Represent flag sets with the `bitflags` crate, not enums. (C-BITFLAG) - Offer a builder for types with many or optional inputs. (C-BUILDER) - Validate arguments — prefer types that make invalid states unrepresentable; otherwise check and return `Result`. (C-VALIDATE) ## Future-proofing - Keep struct fields private; expose accessors/setters so the representation can evolve. (C-STRUCT-PRIVATE, C-NEWTYPE-HIDE) - Seal traits not meant for downstream impl via a private supertrait, so you can add methods without breaking. (C-SEALED) - Mark enums (and structs) you may extend with `#[non_exhaustive]` so adding variants/fields is non-breaking. - Do not duplicate `derive`d trait bounds on the struct itself — adding a bound is a breaking change; deriving more traits is not. (C-STRUCT-BOUNDS) ## Docs - Crate-level docs are thorough with examples; every public item has a rustdoc example. (C-CRATE-DOC, C-EXAMPLE) - Examples use `?`, never `unwrap()` or `try!`. (C-QUESTION-MARK) - Hide internals with `#[doc(hidden)]` / `pub(crate)`. (C-HIDDEN) ## Don't - Don't hand-implement `Into`/`TryInto`, or add `get_` to getters. - Don't expose public fields just to skip writing accessors. - Don't panic in `Drop`, and don't take out-parameters — return values instead. - Don't add a generic trait bound to a struct that you only need on its impls.