Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Idiomatic Rust code guidance based on Apollo GraphQL's best practices handbook for ownership, errors, and performance.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/chapter_02.md
1# Chapter 2 - Clippy and Linting Discipline23Be sure to have `cargo clippy` installed with your rust compiler, run `cargo clippy -V` in your terminal for a rust project and you should get something like this `clippy 0.1.86 (05f9846f89 2025-03-31)`. If terminal fails to show a clippy version, please run the following code `rustup update && rustup component add clippy`.45Clippy documentation can be found [here](https://doc.rust-lang.org/clippy/usage.html).67## 2.1 Why care about linting?89Rust compiler is a powerful tool that catches many mistakes. However, some more in-depth analysis require extra tools, that is where `cargo clippy` clippy comes into to play. Clippy checks for:10* Performance pitfalls.11* Style issues.12* Redundant code.13* Potential bugs.14* Non-idiomatic Rust.1516## 2.2 Always run `cargo clippy`1718Add the following to your daily workflow:1920```shell21$ cargo clippy --all-targets --all-features --locked -- -D warnings22```2324* `--all-targets`: checks library, tests, benches and examples.25* `--all-features`: checks code for all features enabled, auto solves conflicting features.26* `--locked`: Requires `Cargo.lock` to be up-to-date, can be solved with `$ cargo update`.27* `-D warnings`: treats warnings as errors2829Potential additions elements to add:3031* `-- -W clippy::pedantic`: lints which are rather strict or have occasional false positives.32* `-- -W clippy::nursery`: Optionally can be added to check for new lints that are still under development.33* ❗ Add this to your Makefile, Justfile, xtask or CI Pipeline.3435> Example at ApolloGraphQL36>37> In the `Router` project there is a `xtask` configured for linting that can be executed with `cargo xtask lint`.3839## 2.3 Important Clippy Lints to Respect4041| Lint Name | Why | Link |42| --------- | ----| -----|43| `redundant_clone` | Detects unnecessary `clones`, has performance impact | [link (nursery + perf)](https://rust-lang.github.io/rust-clippy/master/#redundant_clone) |44| `needless_borrow` group | Removes redundant `&` borrowing | [link (style)](https://rust-lang.github.io/rust-clippy/master/#needless_borrow) |45| `map_unwrap_or` / `map_or` | Simplifies nested `Option/Result` handling | [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/#map_unwrap_or) [`unnecessary_map_or`](https://rust-lang.github.io/rust-clippy/master/#unnecessary_map_or) [`unnecessary_result_map_or_else`](https://rust-lang.github.io/rust-clippy/master/#unnecessary_result_map_or_else) |46| `manual_ok_or` | Suggest using `.ok_or_else` instead of `match` | [link (style)](https://rust-lang.github.io/rust-clippy/master/#manual_ok_or) |47| `large_enum_variant` | Warns if an enum has very large variant which is bad for memory. Suggests `Boxing` it | [link (perf)](https://rust-lang.github.io/rust-clippy/master/#large_enum_variant) |48| `unnecessary_wraps` | If your function always returns `Some` or `Ok`, you don't need `Option`/`Result` | [link (pedantic)](https://rust-lang.github.io/rust-clippy/master/#unnecessary_wraps) |49| `clone_on_copy` | Catches accidental `.clone()` on `Copy` types like `u32` and `bool` | [link (complexity)](https://rust-lang.github.io/rust-clippy/master/#clone_on_copy) |50| `needless_collect` | Prevents collecting and allocating an iterator, when allocation is not needed | [link (nursery)](https://rust-lang.github.io/rust-clippy/master/#needless_collect) |5152## 2.4 Fix warnings, don't silence them!5354**NEVER** just `#[allow(clippy::lint_something)]` unless:5556* You **truly understand** why the warning happens and you have a reason why it is better that way.57* You **document** why it is being ignored.58* ❗ Don't use `allow`, but `expect`, it will give a warning in case the lint is not true anymore, `#[expect(clippy::lint_something)]`.5960### Example:6162```rust63// Faster matching is preferred over size efficiency64#[expect(clippy::large_enum_variant)]65enum Message {66Code(u8),67Content([u8; 1024]),68}69```7071> The fix would be:72>73> ```rust74> // Faster matching is preferred over size efficiency75> #[expect(clippy::large_enum_variant)]76> enum Message {77> Code(u8),78> Content(Box<[u8; 1024]>),79> }80> ```8182### Handling false positives8384Sometimes Clippy complains even when your code is correct, in those cases there are two solutions:851. Try to refactor the code, so it improves the warning.862. **Locally** override the lint with `#[expect(clippy::lint_name)]` and a comment with the reason.873. Avoid global overrides, unless it is core crate issue, a good example of this is the Bevy Engine that has a set of lints that should be allowed by default.8889## 2.5 Configure workspace/package lints9091In your `Cargo.toml` file it is possible to determine which lints and their priorities over each other. In case of 2 or more conflicting lints, the higher priority one will be chosen. Example configuration for a package:9293```toml94[lints.rust]95future-incompatible = "warn"96nonstandard_style = "deny"9798[lints.clippy]99all = { level = "deny", priority = 10 }100redundant_clone = { level = "deny", priority = 9 }101manual_while_let_some = { level = "deny", priority = 4 }102pedantic = { level = "warn", priority = 3 }103```104105And for a workspace:106107```toml108[workspace.lints.rust]109future-incompatible = "warn"110nonstandard_style = "deny"111112[workspace.lints.clippy]113all = { level = "deny", priority = 10 }114redundant_clone = { level = "deny", priority = 9 }115manual_while_let_some = { level = "deny", priority = 4 }116pedantic = { level = "warn", priority = 3 }117```118