4 min read
On this page

Essential Tools

Rust ships with a toolchain that makes it productive from day one. Where other languages require you to find and configure linters, formatters, and build tools separately, Rust bundles them into the standard installation. This topic covers the tools you should be using on every project.

Clippy: The Linter

Clippy catches common mistakes, suggests idiomatic alternatives, and enforces style. It is not just a linter — it is a teacher.

cargo clippy
warning: manual implementation of `Option::map`
  --> src/main.rs:12:5
   |
12 | /     match opt {
13 | |         Some(x) => Some(x * 2),
14 | |         None => None,
15 | |     }
   | |_____^ help: try: `opt.map(|x| x * 2)`

Clippy has hundreds of lints organized by category:

  • correctness — things that are almost certainly bugs
  • style — idiomatic Rust patterns
  • complexity — code that can be simplified
  • perf — performance improvements
  • pedantic — stricter suggestions

Enable pedantic lints for maximum feedback:

// At the top of main.rs or lib.rs
#![warn(clippy::pedantic)]

Run Clippy in CI. It catches real bugs. A codebase that passes Clippy is measurably more idiomatic than one that does not.

Rustfmt: The Formatter

Rustfmt enforces consistent code style. No more debates about brace placement or line length.

cargo fmt

That is it. Every file is formatted to the community standard. Run it on save, run it in CI, never think about formatting again.

Customize behavior with rustfmt.toml:

# rustfmt.toml
max_width = 100
tab_spaces = 4
edition = "2021"
imports_granularity = "Crate"
group_imports = "StdExternalCrate"

Most teams keep the defaults. The value of rustfmt is not in its configuration but in the fact that everyone uses the same settings.

Check formatting without modifying files (useful in CI):

cargo fmt -- --check

Cargo Watch: Rebuild on Save

Cargo Watch recompiles your project every time you save a file:

cargo install cargo-watch
cargo watch -x check

This runs cargo check (type checking without a full build) on every file change. Fast feedback — you see errors within a second of saving.

Common patterns:

# Check on save
cargo watch -x check

# Run tests on save
cargo watch -x test

# Check, then test, then clippy
cargo watch -x check -x test -x clippy

# Run the application on save
cargo watch -x run

Cargo Watch is the closest thing Rust has to a REPL-like workflow. Write code, save, see results.

Cargo Edit: Manage Dependencies

Cargo Edit adds shell commands for managing Cargo.toml dependencies:

cargo install cargo-edit
# Add a dependency
cargo add serde --features derive
cargo add tokio --features full

# Add a dev dependency
cargo add --dev criterion

# Remove a dependency
cargo rm unused_crate

# Upgrade dependencies
cargo upgrade

Without Cargo Edit, you manually edit Cargo.toml and look up version numbers on crates.io. With it, dependency management is a one-liner.

cargo upgrade checks for newer compatible versions and updates your Cargo.toml:

cargo upgrade
    Upgrading serde v1.0.190 -> v1.0.195
    Upgrading tokio v1.34.0 -> v1.35.1

Rust Analyzer: IDE Support

Rust Analyzer provides IDE-level intelligence for any editor that supports LSP (Language Server Protocol). It powers the Rust experience in VS Code, Neovim, Emacs, Helix, and others.

Features:

  • Real-time error checking — red squiggles as you type
  • Go to definition — jump to any function, type, or module
  • Inline type hints — see inferred types without hovering
  • Code completion — method suggestions, import resolution
  • Refactoring — rename, extract function, inline variable
  • Macro expansion — see what a macro generates

Install it through your editor's extension marketplace. In VS Code, search for "rust-analyzer" and install. It replaces the older RLS (Rust Language Server).

Configuration worth changing:

// .vscode/settings.json
{
    "rust-analyzer.checkOnSave.command": "clippy",
    "rust-analyzer.inlayHints.typeHints.enable": true,
    "rust-analyzer.inlayHints.parameterHints.enable": true
}

Setting checkOnSave.command to clippy means you get Clippy feedback in real time, not just on manual runs.

Cargo Expand: See Generated Code

When macros confuse you, cargo expand shows the expanded code:

cargo install cargo-expand
#[derive(Debug, Clone)]
struct Point {
    x: f64,
    y: f64,
}
cargo expand

Shows the full Debug and Clone implementations that the derive macros generated. Invaluable for understanding what proc macros do.

Cargo Audit: Security Vulnerabilities

Check your dependencies for known security vulnerabilities:

cargo install cargo-audit
cargo audit
Crate:  openssl
Version: 0.10.55
Warning: RUSTSEC-2023-0072
Title:  Memory corruption in openssl
Solution: Upgrade to >= 0.10.60

Run this in CI. It checks against the RustSec advisory database.

Miri: Undefined Behavior Detector

Miri is an interpreter for Rust that detects undefined behavior in unsafe code:

rustup +nightly component add miri
cargo +nightly miri test
error: Undefined Behavior: dereferencing pointer failed: 0x1 is not a valid pointer

Miri catches use-after-free, out-of-bounds access, alignment violations, and aliasing violations that would otherwise be silent UB. Run it on any code that uses unsafe.

The CI Pipeline

A minimal but effective CI setup:

# Check formatting
cargo fmt -- --check

# Run clippy
cargo clippy -- -D warnings

# Run tests
cargo test

# Check for security vulnerabilities
cargo audit

This catches formatting issues, lint warnings (promoted to errors with -D warnings), test failures, and known vulnerabilities. Four commands, comprehensive coverage.

Common Pitfalls

  • Ignoring Clippy warnings. Clippy is not noise. Each warning is a suggestion to write better code. Suppress individual lints with #[allow(clippy::...)] when you disagree, but address most of them.
  • Not running rustfmt. Inconsistent formatting creates noisy diffs and wastes review time. Format on save.
  • Skipping cargo audit in CI. Dependencies accumulate vulnerabilities over time. Automated checks catch them before deployment.
  • Using Rust Analyzer without Clippy integration. Set checkOnSave.command to clippy for real-time lint feedback in your editor.
  • Not using cargo watch during development. Waiting for manual builds breaks flow. Automatic recompilation keeps you in the loop.

Key Takeaways

  • Clippy catches bugs and enforces idiomatic Rust. Run it on every project, in CI, and integrated with your editor.
  • Rustfmt eliminates formatting debates. Configure it once and never think about style again.
  • Cargo Watch provides instant feedback by recompiling on save.
  • Cargo Edit simplifies dependency management with cargo add, cargo rm, and cargo upgrade.
  • Rust Analyzer is the IDE backbone. Configure it to run Clippy on save for maximum value.
  • Use Miri for unsafe code and cargo audit for dependency security. Both belong in CI.