Skip to content

Commit bbfff70

Browse files
authored
docs: update lint registration for statically-combined passes (#17178)
Follow up after #17124 and #17132 changelog: none
2 parents d00aff4 + fdadd62 commit bbfff70

3 files changed

Lines changed: 33 additions & 27 deletions

File tree

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

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/

0 commit comments

Comments
 (0)