Item 29: Listen to Clippy

"It looks like you're writing a letter. Would you like help?" – Microsoft Clippit

Item 31 describes the ecosystem of helpful tools available in the Rust toolbox, but one tool is sufficiently helpful and important to get promoted to an Item of its very own: Clippy.

Clippy is an additional component for Cargo (cargo clippy) that emits warnings about your Rust usage, across a variety of categories:

  • Correctness: Warns about common programming errors
  • Idiom: Warns about code constructs that aren't quite in standard Rust style
  • Concision: Points out variations on the code that are more compact
  • Performance: Suggests alternatives that avoid unnecessary processing or allocation
  • Readability: Describes alterations to the code that would make it easier for humans to read and understand

For example, the following code builds fine:

#![allow(unused)]
fn main() {
pub fn circle_area(radius: f64) -> f64 {
    let pi = 3.14;
    pi * radius * radius
}
}

but Clippy points out that the local approximation to π is unnecessary and inaccurate:

error: approximate value of `f{32, 64}::consts::PI` found
 --> src/main.rs:5:18
  |
5 |         let pi = 3.14;
  |                  ^^^^
  |
  = help: consider using the constant directly
  = help: for further information visit
    https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
  = note: `#[deny(clippy::approx_constant)]` on by default

The linked webpage explains the problem and points the way to a suitable modification of the code:

#![allow(unused)]
fn main() {
pub fn circle_area(radius: f64) -> f64 {
    std::f64::consts::PI * radius * radius
}
}

As shown previously, each Clippy warning comes with a link to a webpage describing the error, which explains why the code is considered bad. This is vital, because it allows you to decide whether those reasons apply to your code or whether there is some particular reason why the lint check isn't relevant. In some cases, the text also describes known problems with the lint, which might explain an otherwise confusing false positive.

If you decide that a lint warning isn't relevant for your code, you can disable it either for that particular item (#[allow(clippy::some_lint)]) or for the entire crate (#![allow(clippy::some_lint)], with an extra !, at the top level). However, it's usually better to take the cost of a minor refactoring of the code than to waste time and energy arguing about whether the warning is a genuine false positive.

Whether you choose to fix or disable the warnings, you should make your code Clippy-warning free.

That way, when new warnings appear—whether because the code has been changed or because Clippy has been upgraded to include new checks—they will be obvious. Clippy should also be enabled in your CI system (Item 32).

Clippy's warnings are particularly helpful when you're learning Rust, because they reveal gotchas you might not have noticed and help you become familiar with Rust idiom.

Many of the Items in this book also have corresponding Clippy warnings, when it's possible to mechanically check the relevant concern:

As the size of this list should make clear, it can be a valuable learning experience to read the list of Clippy lint warnings—including the checks that are disabled by default because they are overly pedantic or because they have a high rate of false positives. Even though you're unlikely to want to enable these warnings for your code, understanding the reasons why they were written in the first place will improve your understanding of Rust and its idiom.