Skip to content

Commit 50119f3

Browse files
committed
Cleanup attributes in Clippy source files
10 parents f6e7838 + e19db29 + 3ed8234 + 368ead0 + b30ee46 + 2dd917e + 2c55f1e + 9bd159a + 4d542ee + 53308b5 commit 50119f3

1,734 files changed

Lines changed: 13545 additions & 11345 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,101 @@ document.
66

77
## Unreleased / Beta / In Rust Nightly
88

9-
[df995e...master](https://github.com/rust-lang/rust-clippy/compare/df995e...master)
9+
[88f787...master](https://github.com/rust-lang/rust-clippy/compare/88f787...master)
10+
11+
## Rust 1.96
12+
13+
Current stable, released 2026-05-28
14+
15+
[View all 48 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2026-02-24T12%3A30%3A17Z..2026-04-03T17%3A32%3A48Z+base%3Amaster)
16+
17+
### New Lints
18+
19+
* Added [`manual_noop_waker`] to `complexity`
20+
[#16687](https://github.com/rust-lang/rust-clippy/pull/16687)
21+
* Added [`manual_option_zip`] to `complexity`
22+
[#16600](https://github.com/rust-lang/rust-clippy/pull/16600)
23+
* Added [`manual_pop_if`] to `complexity`
24+
[#16582](https://github.com/rust-lang/rust-clippy/pull/16582)
25+
26+
### Enhancements
27+
28+
* [`explicit_counter_loop`] suggest `(init..).take(n)` when loop variable is unused and range is
29+
`0..n`
30+
[#16658](https://github.com/rust-lang/rust-clippy/pull/16658)
31+
* [`iter_kv_map`] handle identity map for `map` and `flat_map`
32+
[#16743](https://github.com/rust-lang/rust-clippy/pull/16743)
33+
* [`manual_noop_waker`] add an MSRV check
34+
[#16850](https://github.com/rust-lang/rust-clippy/pull/16850)
35+
* [`manual_pop_if`] in case the popped value is used, just emit the lint with no suggestion
36+
[#16683](https://github.com/rust-lang/rust-clippy/pull/16683)
37+
* [`manual_pop_if`] also cover `.pop().unwrap_unchecked()`
38+
[#16683](https://github.com/rust-lang/rust-clippy/pull/16683)
39+
* [`manual_pop_if`] detect manual implementations of `BinaryHeap::pop_if()`
40+
[#16734](https://github.com/rust-lang/rust-clippy/pull/16734)
41+
* [`unnecessary_option_map_or_else`] function definitions are no longer traversed when checking if
42+
an expression is the identity
43+
[#15889](https://github.com/rust-lang/rust-clippy/pull/15889)
44+
* [`unnecessary_result_map_or_else`] function definitions are no longer traversed when checking if
45+
an expression is the identity
46+
[#15889](https://github.com/rust-lang/rust-clippy/pull/15889)
47+
* [`question_mark`] fix suggestion-caused error caused by semicolon inference relying only on
48+
parent-node shape
49+
[#16656](https://github.com/rust-lang/rust-clippy/pull/16656)
50+
* Format-related lints now handle `core::panic!`
51+
[#16597](https://github.com/rust-lang/rust-clippy/pull/16597)
52+
* [`explicit_counter_loop`] fix FN when the initializer is not integral
53+
[#16647](https://github.com/rust-lang/rust-clippy/pull/16647)
54+
* [`suboptimal_flops`] fix FN on add and sub assign
55+
[#16625](https://github.com/rust-lang/rust-clippy/pull/16625)
56+
* [`infinite_loop`] fix wrong suggestion to add `-> !` when the loop is inside a conditional branch
57+
[#16619](https://github.com/rust-lang/rust-clippy/pull/16619)
58+
* [`unnecessary_cast`] preserve parentheses in presence of cascaded casts
59+
[#16483](https://github.com/rust-lang/rust-clippy/pull/16483)
60+
* [`cmp_owned`] fix wrong suggestions on `PathBuf`
61+
[#16628](https://github.com/rust-lang/rust-clippy/pull/16628)
62+
* [`redundant_closure`] fix wrong suggestions when local is dereferenced to callable
63+
[#16648](https://github.com/rust-lang/rust-clippy/pull/16648)
64+
65+
### False Positive Fixes
66+
67+
* [`collapsible_if`] fix FP when the inner if contains cfg
68+
[#16757](https://github.com/rust-lang/rust-clippy/pull/16757)
69+
* [`collapsible_match`] fix FP when the pat binding is moved or mutated
70+
[#16708](https://github.com/rust-lang/rust-clippy/pull/16708)
71+
* [`collapsible_match`] fix a case where a suggested transformation changes runtime behavior
72+
[#16878](https://github.com/rust-lang/rust-clippy/pull/16878)
73+
* [`match_same_arms`] fix FP with associated consts
74+
[#16701](https://github.com/rust-lang/rust-clippy/pull/16701)
75+
* [`semicolon_inside_block`] fix FP in `try` blocks where moving `;` changes the block's return
76+
type and causes type errors
77+
[#16697](https://github.com/rust-lang/rust-clippy/pull/16697)
78+
* [`unnecessary_safety_comment`] fix FP on code blocks inside inner docs
79+
[#16559](https://github.com/rust-lang/rust-clippy/pull/16559)
80+
* [`doc_paragraphs_missing_punctuation`] no longer lints punctuated paragraphs with a trailing
81+
emoji
82+
[#16514](https://github.com/rust-lang/rust-clippy/pull/16514)
83+
84+
### ICE Fixes
85+
86+
* [`match_same_arms`] fix ICE in `match_same_arms`
87+
[#16685](https://github.com/rust-lang/rust-clippy/pull/16685)
88+
* [`nonminimal_bool`] fix ICE in `swap_binop()` by using the proper `TypeckResults`
89+
[#16659](https://github.com/rust-lang/rust-clippy/pull/16659)
90+
* Fix ICE when using the `min_generic_const_args` incomplete feature
91+
[#16692](https://github.com/rust-lang/rust-clippy/pull/16692)
92+
93+
### Documentation Improvements
94+
95+
* [`similar_names`] changed the lint docs to reflect its actual behavior
96+
[#16300](https://github.com/rust-lang/rust-clippy/pull/16300)
97+
98+
### Performance Improvements
99+
100+
* [`repeat_vec_with_capacity`] optimized by 96.876% (784M -> 24M instructions)
101+
[#16756](https://github.com/rust-lang/rust-clippy/pull/16756)
102+
* [`manual_is_ascii_check`] optimized by 97.125% (822M -> 23M instructions)
103+
[#16755](https://github.com/rust-lang/rust-clippy/pull/16755)
10104

11105
## Rust 1.95
12106

@@ -6746,6 +6840,7 @@ Released 2018-09-13
67466840
[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option
67476841
[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result
67486842
[`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles
6843+
[`for_unbounded_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_unbounded_range
67496844
[`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy
67506845
[`forget_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_non_drop
67516846
[`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref
@@ -6906,6 +7001,7 @@ Released 2018-09-13
69067001
[`manual_is_multiple_of`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_multiple_of
69077002
[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two
69087003
[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and
7004+
[`manual_isolate_lowest_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_isolate_lowest_one
69097005
[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
69107006
[`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
69117007
[`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
@@ -7376,6 +7472,7 @@ Released 2018-09-13
73767472
[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
73777473
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
73787474
[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
7475+
[`unused_async_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async_trait_impl
73797476
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
73807477
[`unused_enumerate_index`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_enumerate_index
73817478
[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs

CONTRIBUTING.md

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,11 @@ To have `rust-analyzer` also work in the `clippy_dev` and `lintcheck` crates, ad
124124

125125
## How Clippy works
126126

127-
[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers in the [`LintStore`].
128-
For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this:
127+
[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers them in the
128+
[`LintStore`]. All early passes are folded into a single `CombinedEarlyLintPass`, and all late passes into a single
129+
`CombinedLateLintPass`, each registered once with the store. A pass is added to one of these by listing it in the
130+
`early_lint_methods!` or `late_lint_methods!` macro invocation. For example, the
131+
[`else_if_without_else`][else_if_without_else] lint is added like this:
129132

130133
```rust
131134
// ./clippy_lints/src/lib.rs
@@ -134,18 +137,21 @@ For example, the [`else_if_without_else`][else_if_without_else] lint is register
134137
pub mod else_if_without_else;
135138
// ...
136139

137-
pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
138-
// ...
139-
store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
140-
// ...
141-
}
140+
rustc_lint::early_lint_methods!(
141+
crate::combined_early_lint_pass,
142+
[CombinedEarlyLintPass, (/* ... */), [
143+
// ...
144+
ElseIfWithoutElse: else_if_without_else::ElseIfWithoutElse = else_if_without_else::ElseIfWithoutElse,
145+
// ...
146+
]]
147+
);
142148
```
143149

144-
The [`rustc_lint::LintStore`][`LintStore`] provides two methods to register lints:
145-
[register_early_pass][reg_early_pass] and [register_late_pass][reg_late_pass]. Both take an object
146-
that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in
147-
every single lint. It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `cargo dev
148-
update_lints`. When you are writing your own lint, you can use that script to save you some time.
150+
Each entry has the form `Field: Type = constructor`, where the constructor builds the pass (passing `conf` when the pass
151+
needs the user configuration). The combined passes implement [`EarlyLintPass`][early_lint_pass] and
152+
[`LateLintPass`][late_lint_pass] respectively, so each listed pass must also implement the matching trait. It's worth
153+
noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `cargo dev update_lints`. When you are
154+
writing your own lint, you can use that script to save you some time.
149155

150156
```rust
151157
// ./clippy_lints/src/else_if_without_else.rs
@@ -167,14 +173,12 @@ The difference between `EarlyLintPass` and `LateLintPass` is that the methods of
167173
AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information
168174
via the `LateContext` parameter.
169175

170-
That's why the `else_if_without_else` example uses the `register_early_pass` function. Because the
176+
That's why the `else_if_without_else` example is listed in `early_lint_methods!`. Because the
171177
[actual lint logic][else_if_without_else] does not depend on any type information.
172178

173179
[lint_crate_entry]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
174180
[else_if_without_else]: https://github.com/rust-lang/rust-clippy/blob/4253aa7137cb7378acc96133c787e49a345c2b3c/clippy_lints/src/else_if_without_else.rs
175181
[`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html
176-
[reg_early_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_early_pass
177-
[reg_late_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_late_pass
178182
[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html
179183
[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
180184

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clippy"
3-
version = "0.1.97"
3+
version = "0.1.98"
44
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
55
repository = "https://github.com/rust-lang/rust-clippy"
66
readme = "README.md"
@@ -34,7 +34,7 @@ anstream = "0.6.18"
3434

3535
[dev-dependencies]
3636
cargo_metadata = "0.23"
37-
ui_test = "0.30.5"
37+
ui_test = "0.30.7"
3838
regex = "1.5.5"
3939
serde = { version = "1.0.145", features = ["derive"] }
4040
serde_json = "1.0.122"

book/src/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
8989
#### Lints Section in `Cargo.toml`
9090

9191
Finally, lints can be allowed/denied using [the lints
92-
section](https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-lints-section)) in the `Cargo.toml` file:
92+
section](https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-lints-section) in the `Cargo.toml` file:
9393

9494
To deny `clippy::enum_glob_use`, put the following in the `Cargo.toml`:
9595

book/src/development/adding_lints.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -282,21 +282,22 @@ When using `cargo dev new_lint`, the lint is automatically registered and
282282
nothing more has to be done.
283283

284284
When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
285-
pass may have to be registered manually in the `register_lints` function in
286-
`clippy_lints/src/lib.rs`:
285+
pass may have to be registered manually by adding an entry to the
286+
`early_lint_methods!` macro invocation in `clippy_lints/src/lib.rs`, at the
287+
`// add early passes here` marker:
287288

288289
```rust,ignore
289-
store.register_early_pass(|| Box::new(foo_functions::FooFunctions));
290+
FooFunctions: foo_functions::FooFunctions = foo_functions::FooFunctions,
290291
```
291292

292-
As one may expect, there is a corresponding `register_late_pass` method
293-
available as well. Without a call to one of `register_early_pass` or
294-
`register_late_pass`, the lint pass in question will not be run.
293+
As one may expect, there is a corresponding `late_lint_methods!` macro available
294+
as well. Without an entry in one of `early_lint_methods!` or `late_lint_methods!`,
295+
the lint pass in question will not be run.
295296

296297
One reason that `cargo dev update_lints` does not automate this step is that
297298
multiple lints can use the same lint pass, so registering the lint pass may
298299
already be done when adding a new lint. Another reason that this step is not
299-
automated is that the order that the passes are registered determines the order
300+
automated is that the order that the passes are listed determines the order
300301
the passes actually run, which in turn affects the order that any emitted lints
301302
are output in.
302303

book/src/development/defining_lints.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,18 +184,19 @@ However, sometimes we might want to declare a new lint by hand. In this case,
184184
we'd use `cargo dev update_lints` command afterwards.
185185

186186
When a lint is manually declared, we might need to register the lint pass
187-
manually in the `register_lints` function in `clippy_lints/src/lib.rs`:
187+
manually by adding an entry to the `late_lint_methods!` macro invocation in
188+
`clippy_lints/src/lib.rs`, at the `// add late passes here` marker:
188189

189190
```rust
190-
store.register_late_pass(|_| Box::new(foo_functions::FooFunctions));
191+
FooFunctions: foo_functions::FooFunctions = foo_functions::FooFunctions,
191192
```
192193

193194
As you might have guessed, where there's something late, there is something
194-
early: in Clippy there is a `register_early_pass` method as well. More on early
195+
early: in Clippy there is an `early_lint_methods!` macro as well. More on early
195196
vs. late passes in the [Lint Passes] chapter.
196197

197-
Without a call to one of `register_early_pass` or `register_late_pass`, the lint
198-
pass in question will not be run.
198+
Without an entry in one of `early_lint_methods!` or `late_lint_methods!`, the
199+
lint pass in question will not be run.
199200

200201

201202
[all_lints]: https://rust-lang.github.io/rust-clippy/master/

book/src/development/emitting_lints.md

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ LL | for _ in 1..1 + 1 {}
8888
| ^^^^^^^^ help: use: `1..=1`
8989
```
9090

91+
### Applicability
92+
9193
**Not all suggestions are always right**, some of them require human
9294
supervision, that's why we have [Applicability][applicability].
9395

@@ -105,23 +107,26 @@ impl<'tcx> LateLintPass<'tcx> for LintName {
105107
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
106108
// Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint
107109
if some_lint_expr_logic(expr) {
108-
span_lint_and_sugg( // < Note this change
110+
span_lint_and_then( // < Note this change
109111
cx,
110112
LINT_NAME,
111-
span,
113+
expr.span,
112114
"message on why the lint is emitted",
113-
"use",
114-
format!("foo + {} * bar", snippet(cx, expr.span, "<default>")), // < Suggestion
115-
Applicability::MachineApplicable,
115+
|diag| {
116+
// v Build and emit the suggestion
117+
let mut app = Applicability::MachineApplicable;
118+
let expr_snippet = snippet_with_applicability(cx, expr.span, "_", &mut app);
119+
let sugg = format!("foo + {expr_snippet} * bar");
120+
diag.span_suggestion(expr.span, "use", sugg, app);
121+
}
116122
);
117123
}
118124
}
119125
}
120126
```
121127

122128
Suggestions generally use the [`format!`][format_macro] macro to interpolate the
123-
old values with the new ones. To get code snippets, use one of the `snippet*`
124-
functions from `clippy_utils::source`.
129+
old values with the new ones. For information on getting code snippets, see [Snippets](emitting_lints.md#snippets).
125130

126131
## How to choose between notes, help messages and suggestions
127132

@@ -183,13 +188,50 @@ error: This `.fold` can be more succinctly expressed as `.any`
183188
|
184189
```
185190

186-
### Snippets
191+
## Snippets
187192

188193
Snippets are pieces of the source code (as a string), they are extracted
189-
generally using the [`snippet`][snippet_fn] function.
194+
generally using the various `snippet_*` functions from [`clippy_utils::source`][].
195+
196+
If you're using the snippets _not_ to build a suggestion, it's usually
197+
enough to use [`snippet`][snippet_fn] -- it accepts the span of the item, and
198+
also a fallback string (see [Fallback string](emitting_lints.md#fallback-string)).
190199

191200
For example, if you want to know how an item looks (and you know the item's
192-
span), you could use `snippet(cx, span, "..")`.
201+
span), you could use `snippet(cx, span, "_")`.
202+
203+
If you do use the snippet for a suggestion, it's recommended to use
204+
[`snippet_with_applicability`] instead. This is so that Clippy can reduce the
205+
[applicability](emitting_lints.md#applicability) of the suggestion in case it couldn't extract
206+
the snippet "cleanly" -- see the function's documentation for more information.
207+
208+
It's often necessary to create multiple snippets to build a suggestion, in which
209+
case you'll have the following pattern:
210+
211+
```rust
212+
// inside `span_lint_and_then`
213+
214+
// 1. Create initial applicability.
215+
let mut app = Applicability::MachineApplicable;
216+
217+
// 2. Use it to create all the snippets
218+
let foo_snippet = snippet_with_applicability(cx, foo.span, "_", &mut app);
219+
let bar_snippet = snippet_with_applicability(cx, bar.span, "_", &mut app);
220+
let sugg = format!("{foo_snippet} + {bar_snippet}"); // or whatever
221+
222+
// 3. Use it to emit the final suggestion
223+
diag.span_suggestion(span, msg, sugg, app);
224+
```
225+
226+
### Fallback string
227+
This is the string that is used for the snippet when the source code that the
228+
span points to is unavailable. That mostly only happens when proc-macros
229+
mishandle spans -- see [the section on proc-macros][proc-macro-spans].
230+
231+
Most of the time, the snippets in a suggestion come from a (span of a) single
232+
expression, and so `"_"` is an appropriate fallback string. If you instead
233+
find yourself suggesting to insert multiple statements, or a block--basically
234+
anything "big"--then consider using `".."` instead.
193235

194236
## Final: Run UI Tests to Emit the Lint
195237

@@ -210,8 +252,11 @@ cover in the next chapters.
210252
[`span_lint_and_help`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_help.html
211253
[`span_lint_and_sugg`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html
212254
[`span_lint_and_then`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_then.html
255+
[`clippy_utils::source`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/index.html
213256
[range_plus_one]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
214257
[inclusive_range]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
215258
[applicability]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_errors/enum.Applicability.html
216259
[snippet_fn]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet.html
260+
[`snippet_with_applicability`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet_with_applicability.html
261+
[proc-macro-spans]: macro_expansions.html#the-is_from_proc_macro-function
217262
[format_macro]: https://doc.rust-lang.org/std/macro.format.html

0 commit comments

Comments
 (0)