🎓 A1Learner
🔍

Rust Configuring Clippy

Clippy configuration switches on extra Clippy checks and sets their levels. The [lints.clippy] table in Cargo.toml sets levels for a whole project.

A stricter group wakes up

This greet takes a String and only reads it. The default group says nothing. Switch pedantic on at the top of the crate, and it speaks:

#![warn(clippy::pedantic)]

fn greet(name: String) {
    println!("hello {name}");
}

The group that checks the manifest

The cargo group lints Cargo.toml, not code. A fresh project named clipconf has no description and no license yet. It draws warnings like these:

// at the top of src/main.rs
#![warn(clippy::cargo)]

Deny one lint in code

A deny attribute on one function turns its warning into an error. The build stops. In our test the command failed with exit code 101:

#[deny(clippy::len_zero)]
fn count_items(items: &[i32]) -> bool {
    items.len() == 0
}

Set the level for the whole project

The same deny can live in Cargo.toml instead. No attribute sits in the code. Every build in the project obeys the table:

// in Cargo.toml
[lints.clippy]
len_zero = "deny"

One function opts out

Keep the table deny in place. Add an allow to the one old function that needs its old shape. The build passes again, and the exception sits in writing, on the function itself:

#[allow(clippy::len_zero)]
fn count_items(items: &[i32]) -> bool {
    items.len() == 0
}

A group in the table

The table takes group names, too. This one switches pedantic on for the whole project. The greet from the first snippet draws its warning again:

// in Cargo.toml
[lints.clippy]
pedantic = "warn"

Example

#![warn(clippy::pedantic)]

fn greet(name: &str) {
    println!("hello {name}");
}

fn main() {
    let words = ["hello"];
    let extra = words.len() - 1;
    println!("extra words = {extra}");
    greet("Ferris");
}

Key points

  • Clippy sorts its lints into groups.
  • all is the default set.
  • pedantic is stricter.
  • nursery holds lints still being tested.
  • cargo checks Cargo.toml itself.
  • restriction is a shelf to pick from, not a set to switch on whole
  • Use a crate attribute to switch a group on for one crate.
  • #![warn(clippy::pedantic)] at the top of the crate root does it
  • Use the [lints.clippy] table in Cargo.toml to set levels for a whole project.
  • Cargo passes them to builds, tests, and clippy runs alike
  • A level on one item beats the project setting.
  • An #[allow(...)] on one function lets that function keep its shape while the project stays denied
  • Start a strict project gently.
  • Warn in the table first.
  • Move the lints that bite to deny, one by one
  • rustc lints use the same allow, warn, and deny.
  • Clippy names simply ride in front, like clippy::len_zero.
  • Clippy configuration turns on extra checks beyond the default set and controls how strongly each one speaks.

In this example, pedantic stands guard at the top of the crate. greet takes &str, a borrowed view, so the pass-by-value lint stays quiet. main counts the extra words in its little array and prints extra words = 0. Then it greets Ferris. Run cargo clippy on this program and it reports nothing at all. Strict mode is quiet when the code plays along.

Note

Levels are Rust-wide machinery, not a Clippy invention.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Your Cargo.toml denies a lint for the whole project. One old function needs the banned shape. What do you write?