Vec<T> for growable arrays with owned data

Vec&lt;T&gt; is Rust's dynamic array, stored on the heap. It grows as needed, amortizing allocations. I use Vec for collections of owned data, return values, and when you don't know the size upfront. Common methods: .push() appends, .pop() removes the

Default trait for sensible zero values

The Default trait provides a default value for a type, useful for builder patterns, config merging, and initialization. I derive Default on structs where zero/empty is meaningful. For custom logic, implement it manually. Default::default() is the stan

Drop trait for custom cleanup logic

The Drop trait runs when a value goes out of scope, similar to destructors in C++. I implement Drop for resource handles: closing file descriptors, releasing locks, or logging cleanup. The drop method takes &amp;mut self and can't fail (no Result). Ru

From and Into for type conversions

The From and Into traits provide a standard way to convert between types. Implementing From&lt;T&gt; for your type automatically provides Into&lt;T&gt; via a blanket implementation. I use From for infallible conversions (like String::from("hello")) an

std::fmt::Display for user-facing string representations

Implementing Display lets your types be formatted with {} in format strings. It's for user-facing output, unlike Debug which is for developers. I implement Display for error types, domain models, and anything that might be printed. The trait requires

Cargo.lock for reproducible builds

Cargo generates Cargo.lock to pin exact dependency versions. For binaries, commit the lock file so everyone builds the same dependencies. For libraries, don't commit it (users should resolve their own). The lock file enables reproducible builds: cargo

once_cell for lazy static initialization

once_cell provides Lazy and OnceCell for safe lazy initialization. Unlike lazy_static!, it doesn't require macros. Lazy&lt;T&gt; is initialized on first access via a closure. I use it for config, regex patterns, or expensive-to-create globals. OnceCel

tracing for structured logging and distributed tracing

The tracing crate is the modern standard for instrumentation in async Rust. It provides structured logging with spans (representing work) and events (point-in-time records). Spans can be nested, creating a tree that represents causality. I instrument

tokio::select! for racing multiple async operations

Tokio's select! macro lets you wait on multiple futures simultaneously, proceeding with the first one that completes. I use it for timeouts, graceful shutdown, and racing I/O operations. Each branch is a pattern match on the future's output. If multip

Pin and Unpin for safe self-referential async futures

Pin ensures that a value won't move in memory, which is required for self-referential types like async futures. Most async code hides this complexity, but understanding it helps when you hit compiler errors about Unpin. A type is Unpin if it's safe to

Declarative macros (macro_rules!) for code generation

Declarative macros (macro_rules!) let you write code that writes code, reducing boilerplate. They pattern-match on token trees and expand at compile time. I use them for repetitive patterns like implementing traits for multiple types or generating tes

Type state pattern for compile-time state machines

The typestate pattern uses Rust's type system to encode state machines, making invalid states unrepresentable. Each state is a separate type, and transitions consume self and return a new state. The compiler prevents calling methods that aren't valid