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 that emits warnings about your Rust usage (cargo clippy ...
), across a
variety of categories:
- Correctness: warn about common programming errors.
- Idiom: warn about code constructs that aren't quite in standard Rust style.
- Concision: point out variations on the code that are more compact.
- Performance: suggest alternatives that avoid unnecessary processing or allocation.
- Readability: describe alterations to the code that would make it easier for humans to read and understand.
For example, the following code builds fine:
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
--> clippy/src/main.rs:5:18
|
5 | let pi = 3.14;
| ^^^^
|
= note: `#[deny(clippy::approx_constant)]` on by default
= help: consider using the constant directly
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
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 above, 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)]
). 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 continuous integration 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:
- Item 1 suggests using more expressive types than plain
bool
s, and Clippy will also point out the use of multiplebool
s in function parameters and structures. - Item 3 covers manipulations of
Option
andResult
types, and Clippy points out a few possible redundancies, such as: - Item 3 also suggest that errors should be returned to the caller where possible; Clippy points out some missing opportunities to do that.
- Item 5 described Rust's standard traits, and included some implementation requirements that Clippy checks:
- Item 6 suggests implementing
From
rather thanInto
, which Clippy also suggests. - Item 6 also described casts, and Clippy can warn on:
- Item 9 describes fat pointer types, and various Clippy lints point out scenarios where there are unnecessary extra pointer indirection:
- Item 10 describes the panoply of different ways to manipulate
Iterator
instances; Clippy includes a truly astonishing number of lints that point out combinations of iterator methods that could be simplified. - Item 18 suggests limiting the use of
panic!
or related methods likeexpect
, which Clippy also detects. - Item 21 observes that importing a wildcard version of a crate isn't sensible; Clippy agrees.
- Item 23 suggests avoiding wildcard imports, as does Clippy.
- Item 24 and Item 25 touch on the fact that multiple versions of the same crate can appear in your dependency graph; Clippy can be configured to complain when this happens.
- Item 26 explains the additive nature of Cargo features, and Clippy includes a warning about "negative" feature
names (e.g.
"no-std"
) that are likely to indicate a feature that falls foul of this. - Item 26 also explains that a crate's optional dependencies form part of its feature set, and Clippy warns if there
are explicit feature names
(e.g.
"use-crate-x"
) that could just make use of this instead. - Item 27 describes conventions for documentation comments, and Clippy will also point out:
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 pedantic or high-false-positive checks that are disabled by default. 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.