Clippy (Rust): Lints, Suppressing Warnings & CI Guide

Max WellsMax WellsFounder of Rustify

TL;DR: Clippy is Rust's official lint tool, installed with rustup and run with cargo clippy. It provides 700+ lints across correctness, performance, style, and idiomatic Rust patterns; catching issues the compiler misses. Every Rust project should run Clippy in CI. Configure lints with #[allow(clippy::lint_name)] per-item or in Cargo.toml. Running cargo clippy --fix auto-applies safe suggestions.


What Is Clippy?

Clippy is the official Rust linter; a collection of 700+ rules that catch bugs, suggest idiomatic patterns, and flag performance issues beyond what rustc alone reports.

cargo clippy                     # run lints on current package
cargo clippy --all-targets       # include tests, benches, examples
cargo clippy -- -D warnings      # treat warnings as errors (for CI)
cargo clippy --fix               # auto-apply safe suggestions

Example Clippy catch:

// Clippy: "using `x.len() == 0` is inefficient; use is_empty()"
if my_vec.len() == 0 {
    println!("empty");
}
 
// Clippy's suggestion:
if my_vec.is_empty() {
    println!("empty");
}

What Categories of Lints Does Clippy Have?

Clippy organizes lints into groups; you can enable or deny entire groups.

GroupWhat it catches
clippy::correctnessOutright bugs (enabled by default, deny-level)
clippy::suspiciousProbably-wrong code
clippy::styleNon-idiomatic Rust patterns
clippy::complexityUnnecessarily complex code
clippy::perfPerformance improvements
clippy::pedanticStricter style (not on by default)
clippy::nurseryExperimental lints
clippy::restrictionOpinionated, project-specific rules
# Enable pedantic lints for stricter checking
cargo clippy -- -W clippy::pedantic

How Do You Suppress a Clippy Warning?

Use #[allow(clippy::lint_name)] to silence a specific lint for an item, or add it to Cargo.toml for the whole crate.

// Silence for one function
#[allow(clippy::too_many_arguments)]
fn configure(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32) {}
 
// Silence for one expression
let result = #[allow(clippy::cast_precision_loss)] (large_int as f64);

In Cargo.toml (crate-wide):

[lints.clippy]
too_many_arguments = "allow"
pedantic = "warn"

Always prefer fixing the issue over silencing; use #[allow] only when the lint is genuinely wrong for your use case.


How Do You Run Clippy in CI?

Use -D warnings to make Clippy fail the build on any warning; standard practice for Rust CI pipelines.

# GitHub Actions example
- name: Run Clippy
  run: cargo clippy --all-targets --all-features -- -D warnings

Or deny specific groups in code:

// In lib.rs or main.rs
#![deny(clippy::correctness)]
#![warn(clippy::perf, clippy::style)]

What Are Some Common Clippy Suggestions?

// ❌ → ✅ Use is_empty() instead of len() == 0
if v.len() == 0if v.is_empty()
 
// ❌ → ✅ Use ? instead of unwrap() in fallible functions
let x = some_result.unwrap();  →  let x = some_result?;
 
// ❌ → ✅ Simplify clone on copy types
let x = y.clone();  →  let x = y;  // if y: Copy
 
// ❌ → ✅ Use if-let instead of match with single arm
match opt { Some(v) => use(v), None => {} }  →  if let Some(v) = opt { use(v) }
 
// ❌ → ✅ Use .map() instead of manual match on Option
match opt { Some(v) => Some(v + 1), None => None }  →  opt.map(|v| v + 1)
 
// ❌ → ✅ Avoid needless borrow
fn takes_str(s: &str) {}
takes_str(&String::from("hi"))  →  takes_str("hi")

Frequently Asked Questions

Yes; rustup installs Clippy automatically. Check with cargo clippy --version. If missing: rustup component add clippy.

Clippy runs the compiler internally, so it takes about the same time as a regular cargo check. Incremental compilation applies; only changed files are re-linted.

For new projects, yes; it enforces stricter idioms early. For existing codebases, enabling it can be noisy. Add #[allow(clippy::pedantic)] at the crate level first, then fix lints one at a time.

cargo clippy --fix applies machine-applicable suggestions automatically. Not all lints are auto-fixable; Clippy marks which ones are safe to auto-apply. Review the diff before committing.

rustfmt formats code (whitespace, line breaks, indentation). Clippy lints code (logic, idioms, correctness). They are complementary; use both.


Sources


  • Cargo: Clippy is invoked through cargo clippy
  • Rustup: Clippy is installed and managed through the Rust toolchain
  • Macro: Many Clippy lints target macro usage patterns
  • Criterion: Clippy helps catch wasteful code paths before you benchmark them with Criterion
  • macro-rules: Clippy includes lints for common declarative macro patterns and pitfalls
  • Panic: Clippy warns about panic-prone patterns like unnecessary unwrap() use

Keep Reading

Ready to Land a $120k+ Rust Job in the US or Europe?