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 auditin CI. Dependencies accumulate vulnerabilities over time. Automated checks catch them before deployment. - Using Rust Analyzer without Clippy integration. Set
checkOnSave.commandtoclippyfor real-time lint feedback in your editor. - Not using
cargo watchduring 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, andcargo upgrade. - Rust Analyzer is the IDE backbone. Configure it to run Clippy on save for maximum value.
- Use Miri for unsafe code and
cargo auditfor dependency security. Both belong in CI.