rust-best-practices

Idiomatic Rust coding standards based on Apollo GraphQL's best practices handbook. Covers nine core areas: coding styles and idioms, clippy linting, performance optimization, error handling, testing patterns, generics and dispatch, type state pattern, documentation, and pointer safety Emphasizes borrowing over cloning, Result-based error handling with thiserror/anyhow, and performance profiling with release builds Includes quick reference guidance on ownership patterns, panic avoidance, clippy configuration, test naming conventions, and compile-time state safety via type state pattern Provides specific lints to enforce (redundant_clone, large_enum_variant, needless_collect) and recommends #[expect(...)] over #[allow(...)] with justification comments

INSTALLATION
npx skills add https://github.com/apollographql/skills --skill rust-best-practices
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2a

Borrowing & Ownership

  • Prefer &T over .clone() unless ownership transfer is required
  • Use &#x26;str over String, &#x26;[T] over Vec<T> in function parameters
  • Small Copy types (≤24 bytes) can be passed by value
  • Use Cow<'_, T> when ownership is ambiguous

Error Handling

  • Return Result<T, E> for fallible operations; avoid panic! in production
  • Never use unwrap()/expect() outside tests
  • Use thiserror for library errors, anyhow for binaries only
  • Prefer ? operator over match chains for error propagation

Performance

  • Always benchmark with --release flag
  • Run cargo clippy -- -D clippy::perf for performance hints
  • Avoid cloning in loops; use .iter() instead of .into_iter() for Copy types
  • Prefer iterators over manual loops; avoid intermediate .collect() calls

Linting

Run regularly: cargo clippy --all-targets --all-features --locked -- -D warnings

Key lints to watch:

  • redundant_clone - unnecessary cloning
  • large_enum_variant - oversized variants (consider boxing)
  • needless_collect - premature collection

Use #[expect(clippy::lint)] over #[allow(...)] with justification comment.

Testing

  • Name tests descriptively: process_should_return_error_when_input_empty()
  • One assertion per test when possible
  • Use doc tests (///) for public API examples
  • Consider cargo insta for snapshot testing generated output

Generics &#x26; Dispatch

  • Prefer generics (static dispatch) for performance-critical code
  • Use dyn Trait only when heterogeneous collections are needed
  • Box at API boundaries, not internally

Type State Pattern

Encode valid states in the type system to catch invalid operations at compile time:

struct Connection<State> { /* ... */ _state: PhantomData<State> }

struct Disconnected;

struct Connected;

impl Connection<Connected> {

    fn send(&#x26;self, data: &#x26;[u8]) { /* only connected can send */ }

}

Documentation

  • // comments explain why (safety, workarounds, design rationale)
  • /// doc comments explain what and how for public APIs
  • Every TODO needs a linked issue: // TODO(#42): ...
  • Enable #![deny(missing_docs)] for libraries
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card