rust-lang / rust-lang/rustfmt

Discussion: enable Clippy lints in rustfmt source tree and CI

Open
#6,923 17 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-discussion
Dominant language
Rust
Stars
7k
Forks
1.1k
Avg merge
2d 13h
Merged PRs (30d)
24

Description

Background

We don't currently run Clippy on rustfmt's own code. The rust-clippy job in integration.yml runs Clippy on a bunch of external crates to check that rustfmt formats them correctly; it's a formatter regression test, not a lint check on us. The only Clippy-related thing in the source is a handful of stray #[allow(clippy::*)].

If you run cargo clippy --all-targets against main today (toolchain nightly-2026-02-19), you get 269 lint hits in 50 different lints, all from Clippy's default groups. Most are warnings nobody ever sees. But src/cargo-fmt/main.rs and src/format-diff/main.rs both have #![deny(warnings)] at the top, so a Clippy warning in either of those crates becomes a compile error, and cargo clippy --all-targets doesn't actually finish cleanly. We have a Clippy gate already; it just happens to cover exactly two files by accident.

Which lints would this enable

"Default" means everything in clippy::all:

Group Default What it's about
clippy::correctness deny Code that's almost certainly a bug
clippy::suspicious warn Probably wrong, occasionally intentional
clippy::style warn Idiomatic Rust style
clippy::complexity warn Has a simpler equivalent form
clippy::perf warn Avoidable performance cost

The other groups (pedantic, nursery, restriction, cargo) are allow-by-default and would stay off. Individual lints from those can be opted into later if anyone wants.

Lint reference: https://rust-lang.github.io/rust-clippy/master/index.html

What's firing on main today

Run on nightly-2026-02-19. The four lints marked (E) are the ones currently breaking the build (they have at least one site inside cargo-fmt or format-diff and trip #![deny(warnings)]).

50 lints, 269 sites total
Sites Lint
51 clippy::bool_assert_comparison (E)
41 clippy::unnecessary_map_or
26 clippy::borrow_deref_ref
14 clippy::needless_borrow
13 clippy::explicit_auto_deref
10 clippy::too_many_arguments
9 clippy::field_reassign_with_default
8 clippy::unnecessary_lazy_evaluations
7 clippy::wrong_self_convention
6 clippy::io_other_error (E)
6 clippy::needless_borrows_for_generic_args
6 clippy::expect_fun_call
6 clippy::to_string_in_format_args
6 clippy::arc_with_non_send_sync
5 clippy::redundant_field_names
5 clippy::unnecessary_unwrap
4 clippy::needless_splitn
4 clippy::default_constructed_unit_structs
3 clippy::redundant_pattern
2 clippy::derivable_impls, clippy::useless_conversion, clippy::len_zero, clippy::manual_pattern_char_comparison, clippy::get_first, clippy::while_let_on_iterator, clippy::skip_while_next, clippy::let_unit_value
1 clippy::is_digit_ascii_radix, clippy::nonminimal_bool, clippy::needless_return, clippy::enum_variant_names, clippy::write_with_newline, clippy::needless_lifetimes, clippy::manual_inspect, clippy::ptr_arg, clippy::needless_question_mark, clippy::bind_instead_of_map, clippy::redundant_guards, clippy::clone_on_copy, clippy::collapsible_if, clippy::manual_repeat_n, clippy::borrowed_box, clippy::type_complexity, clippy::extra_unused_lifetimes, clippy::assign_op_pattern, clippy::unwrap_or_default, clippy::legacy_numeric_constants, clippy::map_flatten, clippy::non_canonical_partial_ord_impl (E), clippy::into_iter_on_ref (E)

Suggested next step

Rather than try to agree on the whole list up front, I think the simplest start is one small PR that just lays the plumbing:

  1. Add a [workspace.lints.clippy] table to Cargo.toml with all = "allow". Nothing changes in behavior, and the two cargo-fmt / format-diff build failures go away because there's nothing for #![deny(warnings)] to catch anymore.
  2. Add a cargo clippy --all-targets -- -D warnings step to CI. Safe to turn on immediately, since at this point nothing warns.

After that, each lint we want to actually enforce is its own small PR: flip one entry in the table from "allow" to "warn" (or "deny") and include the fixes for that lint in the same PR. The Cargo.toml ends up being the canonical record of which lints we've consciously adopted, and we never get a flood of unrelated warnings landing together.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Cargo.toml and the rust-clippy job in integration.yml, then run cargo clippy --all-targets on the stated nightly toolchain to reproduce the current failures. Add the workspace Clippy configuration and CI step described in the issue; done means the Clippy command passes without enabling the listed lint groups.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
build-system, ci-cd, tooling
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.