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)
UpperCamelCasefor types, traits, enum variants, and type parameters. Treat acronyms as one word:Uuid, notUUID.snake_casefor modules, functions, methods, locals, and macros (!).SCREAMING_SNAKE_CASEfor constants and statics.- Lifetimes are short and lowercase:
'a,'de,'src. - Getters drop the
get_prefix:fn first(&self), notget_first. Reservegetfor 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 namedIter/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, notuse-std; crate names avoid-rs/-rustsuffixes. (C-FEATURE)
Common traits & interop
- Eagerly derive the standard traits when valid:
Debug,Clone,Copy,PartialEq/Eq,PartialOrd/Ord,Hash,Default; implementDisplaywhere 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-writeInto/TryInto— they come free via blanket impls. (C-CONV-TRAITS) - Collections implement
FromIteratorandExtend. (C-COLLECT) - Gate
serde::Serialize/Deserializebehind aserdefeature. (C-SERDE) - Keep types
Send + Syncwherever the compiler allows. (C-SEND-SYNC) - Generic I/O takes
R: Read/W: Writeby value (callers pass&mut). (C-RW-VALUE)
Error types
- Public error types implement
std::error::Errorand areSend + Sync + 'staticwith usefulDebugandDisplay. (C-GOOD-ERR) - Document failure modes:
# ErrorsforResult-returning fns,# Panicsfor panics,# Safetyforunsafefns. (C-FAILURE) - Destructors never fail or block:
Dropis infallible (a panic inDropduring unwinding aborts). Expose a separateclose()/flush()returningResultfor fallible teardown. (C-DTOR-FAIL, C-DTOR-BLOCK)
Type safety
- Use newtypes to give distinct static meaning to like-shaped values
(
Miles(f64)vsKilometers(f64)). (C-NEWTYPE) - Convey intent through dedicated types/enums, not bare
boolorOptionarguments. (C-CUSTOM-TYPE) - Represent flag sets with the
bitflagscrate, 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
derived 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
?, neverunwrap()ortry!. (C-QUESTION-MARK) - Hide internals with
#[doc(hidden)]/pub(crate). (C-HIDDEN)
Don't
- Don't hand-implement
Into/TryInto, or addget_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.