Skip to content

Commit a4e29c5

Browse files
rylevjyn514
authored andcommitted
Update section of lint store
1 parent 442ba10 commit a4e29c5

File tree

1 file changed

+34
-27
lines changed

1 file changed

+34
-27
lines changed

src/diagnostics/lintstore.md

+34-27
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This page documents some of the machinery around lint registration and how we
44
run lints in the compiler.
55

6-
The `LintStore` is the central piece of infrastructure, around which everything
6+
The [`LintStore`] is the central piece of infrastructure, around which everything
77
rotates. It's not available during the early parts of compilation (i.e., before
88
TyCtxt) in most code, as we need to fill it in with all of the lints, which can only happen after
99
plugin registration.
@@ -19,8 +19,7 @@ boils down to a static with type `&rustc_session::lint::Lint`.
1919

2020
As of <!-- date: 2021-07 --> July 2021, we lint against direct declarations
2121
without the use of the macro today (although this may change in the future, as
22-
the macro is somewhat unwieldy to add new fields to, like all macros by
23-
example).
22+
the macro is somewhat unwieldy to add new fields to, like all macros).
2423

2524
Lint declarations don't carry any "state" - they are merely global identifers and descriptions of
2625
lints. We assert at runtime that they are not registered twice (by lint name).
@@ -34,44 +33,55 @@ lint, and frequently lints are emitted as part of other work (e.g., type checkin
3433

3534
### High-level overview
3635

37-
The lint store is created and all lints are registered during plugin registration, in
38-
[`rustc_interface::register_plugins`]. There are three 'sources' of lint: the internal lints, plugin
39-
lints, and `rustc_interface::Config` [`register_lints`]. All are registered here, in
40-
`register_plugins`.
36+
In [`rustc_interface::register_plugins`] the [`LintStore`] is created and all lints are registered.
37+
There are four 'sources' of lints:
38+
* internal lints: lints only used by the rustc codebase
39+
* builtin lints: lints built into the compiler and not provided by some outside source
40+
* plugin lints: lints created by plugins through the plugin system.
41+
* `rustc_interface::Config`[`register_lints`]: lints passed into the compiler during construction
42+
43+
Lints are registered via the [`LintStore::register_lint`] function. This should
44+
happen just once for any lint, or an ICE will occur.
4145

4246
Once the registration is complete, we "freeze" the lint store by placing it in an `Lrc`. Later in
4347
the driver, it's passed into the `GlobalCtxt` constructor where it lives in an immutable form from
4448
then on.
4549

46-
Lints are registered via the [`LintStore::register_lint`] function. This should
47-
happen just once for any lint, or an ICE will occur.
48-
4950
Lint passes are registered separately into one of the categories (pre-expansion,
5051
early, late, late module). Passes are registered as a closure -- i.e., `impl
5152
Fn() -> Box<dyn X>`, where `dyn X` is either an early or late lint pass trait
5253
object. When we run the lint passes, we run the closure and then invoke the lint
53-
pass methods, which take `&mut self` -- lint passes can keep track of state
54+
pass methods. The lint pass methods take `&mut self` so they can keep track of state
5455
internally.
5556

5657
#### Internal lints
5758

58-
Note, these include both rustc-internal lints, and the traditional lints, like, for example the dead
59-
code lint.
59+
These are lints used just by the compiler or plugins like `clippy`. They can be found in
60+
`rustc_lint::internal`.
61+
62+
An example of such a lint is the check that lint passes are implemented using the `declare_lint_pass!`
63+
macro and not by hand. This is accomplished with the `LINT_PASS_IMPL_WITHOUT_MACRO` lint.
64+
65+
Registration of these lints happens in the [`rustc_lint::register_internals`] function which is
66+
called when constructing a new lint store inside [`rustc_lint::new_lint_store`].
67+
68+
### Builtin Lints
6069

6170
These are primarily described in two places: `rustc_session::lint::builtin` and
62-
`rustc_lint::builtin`. The first provides the definitions for the lints themselves,
63-
and the latter provides the lint pass definitions (and implementations).
71+
`rustc_lint::builtin`. Often the first provides the definitions for the lints themselves,
72+
and the latter provides the lint pass definitions (and implementations), but this is not always
73+
true.
6474

65-
The internal lint registration happens in the [`rustc_lint::register_builtins`] function, along with
66-
the [`rustc_lint::register_internals`] function. More generally, the LintStore "constructor"
67-
function which is *the* way to get a `LintStore` in the compiler (you should not construct it
68-
directly) is [`rustc_lint::new_lint_store`]; it calls the registration functions.
75+
The builtin lint registration happens in the [`rustc_lint::register_builtins`] function. Just like
76+
with internal lints, this happens inside of [`rustc_lint::new_lint_store`].
6977

7078
#### Plugin lints
7179

7280
This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the
73-
mutable `LintStore` during registration to call any functions they need on the `LintStore`, just
74-
like rustc code. Plugins are intended to declare lints with the `plugin` field set to true (e.g., by
81+
mutable `LintStore` during registration (which happens inside of [`rustc_interface::register_plugins`])
82+
and they can call any functions they need on the `LintStore`, just like rustc code.
83+
84+
Plugins are intended to declare lints with the `plugin` field set to true (e.g., by
7585
way of the [`declare_tool_lint!`] macro), but this is purely for diagnostics and help text;
7686
otherwise plugin lints are mostly just as first class as rustc builtin lints.
7787

@@ -86,18 +96,15 @@ within the callback they add. The best way for drivers to get access to this is
8696

8797
Within the compiler, for performance reasons, we usually do not register dozens
8898
of lint passes. Instead, we have a single lint pass of each variety
89-
(e.g. `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
99+
(e.g., `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
90100
individual lint passes; this is because then we get the benefits of static over
91101
dynamic dispatch for each of the (often empty) trait methods.
92102

93-
Ideally, we'd not have to do this, since it certainly adds to the complexity of
103+
Ideally, we'd not have to do this, since it adds to the complexity of
94104
understanding the code. However, with the current type-erased lint store
95105
approach, it is beneficial to do so for performance reasons.
96106

97-
New lints being added likely want to join one of the existing declarations like
98-
`late_lint_mod_passes` in `rustc_lint/src/lib.rs`, which would then
99-
auto-propagate into the other.
100-
107+
[`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html
101108
[`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_lints
102109
[`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html
103110
[`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html

0 commit comments

Comments
 (0)