Rust Clippy
Clippy is a set of extra checks, called lints, for clumsy or risky code. One command, `cargo clippy`, runs it.
A famous constant, typed from memory
Clippy knows the famous constants by heart. Type one from memory and it stops the build. This lint is deny by default. So it arrives as an error, not a warning.
let radius = 2.0f32;
let pi = 3.14f32;
let area = pi * radius * radius;A swap written out by hand
Three lines with a temp variable are a swap wearing a disguise. Clippy spots the shape and names the one-call tool for it:
let temp = first;
first = second;
second = temp;A loop over a single maybe
An Option holds at most one value. Looping over it is a long way to say "if there is one". Clippy says so:
let prize = Some("book");
for p in prize {
println!("you won: {p}");
}Asking the length, meaning emptiness
Comparing a length to zero works, but it makes the reader translate. Clippy points at the word that says it directly:
if name.len() == 0 {
println!("nothing here");
}Let Clippy apply the safe fixes
cargo clippy --fix rewrites the fixes Clippy is sure about, straight into your files. On the four lines above, it fixed the swap and the length check itself. It left the constant and the loop alone. Those two need your judgement, not a rewrite.
cargo clippy --fixOne lint you mean to break
Sometimes the rough value is the whole point — a sketch, a teaching example. The allow attribute switches one named lint off for one item, and stays in the code as your written reason:
#[allow(clippy::approx_constant)]
fn rough_pi() -> f32 {
3.14
}Example
use std::f32::consts::PI;
fn main() {
let radius = 2.0f32;
let area = PI * radius * radius;
println!("area = {area:.2}");
let prize = Some("book");
if let Some(p) = prize {
println!("you won: {p}");
}
let mut first = String::from("blue");
let mut second = String::from("red");
std::mem::swap(&mut first, &mut second);
println!("first = {first}, second = {second}");
let name = String::new();
println!("empty = {}", name.is_empty());
}Key points
- Clippy: a set of extra checks, called lints, that look for clumsy or risky patterns the compiler itself allows
- Use cargo clippy to run every check on your project.
- The messages point at the exact lines.
- The fix is often written out for you.
- Every message names its lint, like clippy::manual_swap.
- The name is a doorway.
- The message links to a page that explains the rule with examples.
- Lint levels: warn prints the message and carries on.
- deny stops the build, like an error.
- Use #[allow(clippy::name)] above one item to switch a single lint off there.
- Do it on purpose, in writing, where a reader can see it.
- If the command is missing, rustup component add clippy installs it.
In this example, every part is the fixed version of a complaint from this lesson. The area uses PI from std::f32::consts — the real constant, not 3.14 typed from memory — and prints area = 12.57. The prize is opened with if let, the honest shape for a single maybe, and prints you won: book. The two names trade places through std::mem::swap, one call instead of the temp-variable dance, so first = red and second = blue. The name is a fresh, empty String. is_empty() says so in one word: empty = true. Run cargo clippy on this program and it reports nothing at all. cargo clippy -- -D warnings passes too. That flag turns every warning into an error.
Note
Clippy arrives with Rust through rustup, next to cargo and rustfmt.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
What does cargo clippy -- -D warnings do?