Rust API Guidelines
Follow the official Rust API guidelines mindset: predictable naming, clear conversions, fallible constructors, and ergonomic but hard-to-misuse types.
Recipe
/// Parses a slug from user input.
pub fn from_str(s: &str) -> Result<Slug, ParseError> { /* ... */ }
impl TryFrom<String> for Slug { /* ... */ }
impl AsRef<str> for Slug { fn as_ref(&self) -> &str { &self.0 } }When to reach for this: Designing any pub crate API consumed by other teams or crates.io.
Working Example
Naming conventions:
| Prefix | Cost | Example |
|---|---|---|
as_ | free | as_str() |
to_ | may alloc | to_string() |
into_ | consumes self | into_inner() |
pub struct Config { /* ... */ }
impl Config {
pub fn builder() -> ConfigBuilder { ConfigBuilder::default() }
pub fn validate(&self) -> Result<(), ValidationError> { /* ... */ }
}What this demonstrates:
- Fallible parsing via
TryFrom/from_strstyle - Cheap borrows via
AsRef - Builder for many optional fields
- Validation methods on built types
Deep Dive
C-GETTER: getters named after field withoutget_prefix unless confusionC-CTOR: constructorsnew,with_*,from_*C-ERROR: error typesErrorsuffix,source()chainC-DEBUG:Debugfor logs,Displayfor users- Interop:
serdebehind feature flag for libraries
Gotchas
- get_ prefix everywhere - unidiomatic. Fix:
fn len(&self)notget_len. - into_ that copies - misleading name. Fix: rename to
to_or true consuming move. - Panicking constructors -
newshould be infallible or return Result. Fix:try_new. - Leaking internal types - future semver prison. Fix: newtype or private fields.
- Feature creep in default features - heavy deps. Fix: optional features documented.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Builder only API | many optional fields | two-field struct |
Deref to inner | transparent wrapper | hiding invariants |
FAQs
Full guidelines URL?
Rust API guidelines book (official) - align team checklist with it.
pub use reexports?
#[doc(inline)] for stable paths; avoid deep internal paths in public docs.
sealed traits?
Prevent downstream impls on extension traits not meant for impl outside crate.
semver for API?
Breaking changes: remove/rename pub items, tighten generics, change Error semantics.
async fn in trait?
Edition 2024 async traits or async_trait crate with documented Send bounds.
Iterator naming?
iter, iter_mut, into_iter standard trio.
error Display vs Debug?
Display user-facing; Debug for engineers; thiserror handles both.
must_use?
On Result-returning builders and futures users must not ignore.
deprecated attr?
#[deprecated(note = "use x")] with migration path before removal.
prelude module?
pub mod prelude { pub use ... } for ergonomic imports.
Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.