Update section of lint store
This commit is contained in:
parent
442ba10f1e
commit
a4e29c5cb5
|
|
@ -3,7 +3,7 @@
|
||||||
This page documents some of the machinery around lint registration and how we
|
This page documents some of the machinery around lint registration and how we
|
||||||
run lints in the compiler.
|
run lints in the compiler.
|
||||||
|
|
||||||
The `LintStore` is the central piece of infrastructure, around which everything
|
The [`LintStore`] is the central piece of infrastructure, around which everything
|
||||||
rotates. It's not available during the early parts of compilation (i.e., before
|
rotates. It's not available during the early parts of compilation (i.e., before
|
||||||
TyCtxt) in most code, as we need to fill it in with all of the lints, which can only happen after
|
TyCtxt) in most code, as we need to fill it in with all of the lints, which can only happen after
|
||||||
plugin registration.
|
plugin registration.
|
||||||
|
|
@ -19,8 +19,7 @@ boils down to a static with type `&rustc_session::lint::Lint`.
|
||||||
|
|
||||||
As of <!-- date: 2021-07 --> July 2021, we lint against direct declarations
|
As of <!-- date: 2021-07 --> July 2021, we lint against direct declarations
|
||||||
without the use of the macro today (although this may change in the future, as
|
without the use of the macro today (although this may change in the future, as
|
||||||
the macro is somewhat unwieldy to add new fields to, like all macros by
|
the macro is somewhat unwieldy to add new fields to, like all macros).
|
||||||
example).
|
|
||||||
|
|
||||||
Lint declarations don't carry any "state" - they are merely global identifers and descriptions of
|
Lint declarations don't carry any "state" - they are merely global identifers and descriptions of
|
||||||
lints. We assert at runtime that they are not registered twice (by lint name).
|
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
|
||||||
|
|
||||||
### High-level overview
|
### High-level overview
|
||||||
|
|
||||||
The lint store is created and all lints are registered during plugin registration, in
|
In [`rustc_interface::register_plugins`] the [`LintStore`] is created and all lints are registered.
|
||||||
[`rustc_interface::register_plugins`]. There are three 'sources' of lint: the internal lints, plugin
|
There are four 'sources' of lints:
|
||||||
lints, and `rustc_interface::Config` [`register_lints`]. All are registered here, in
|
* internal lints: lints only used by the rustc codebase
|
||||||
`register_plugins`.
|
* builtin lints: lints built into the compiler and not provided by some outside source
|
||||||
|
* plugin lints: lints created by plugins through the plugin system.
|
||||||
|
* `rustc_interface::Config`[`register_lints`]: lints passed into the compiler during construction
|
||||||
|
|
||||||
|
Lints are registered via the [`LintStore::register_lint`] function. This should
|
||||||
|
happen just once for any lint, or an ICE will occur.
|
||||||
|
|
||||||
Once the registration is complete, we "freeze" the lint store by placing it in an `Lrc`. Later in
|
Once the registration is complete, we "freeze" the lint store by placing it in an `Lrc`. Later in
|
||||||
the driver, it's passed into the `GlobalCtxt` constructor where it lives in an immutable form from
|
the driver, it's passed into the `GlobalCtxt` constructor where it lives in an immutable form from
|
||||||
then on.
|
then on.
|
||||||
|
|
||||||
Lints are registered via the [`LintStore::register_lint`] function. This should
|
|
||||||
happen just once for any lint, or an ICE will occur.
|
|
||||||
|
|
||||||
Lint passes are registered separately into one of the categories (pre-expansion,
|
Lint passes are registered separately into one of the categories (pre-expansion,
|
||||||
early, late, late module). Passes are registered as a closure -- i.e., `impl
|
early, late, late module). Passes are registered as a closure -- i.e., `impl
|
||||||
Fn() -> Box<dyn X>`, where `dyn X` is either an early or late lint pass trait
|
Fn() -> Box<dyn X>`, where `dyn X` is either an early or late lint pass trait
|
||||||
object. When we run the lint passes, we run the closure and then invoke the lint
|
object. When we run the lint passes, we run the closure and then invoke the lint
|
||||||
pass methods, which take `&mut self` -- lint passes can keep track of state
|
pass methods. The lint pass methods take `&mut self` so they can keep track of state
|
||||||
internally.
|
internally.
|
||||||
|
|
||||||
#### Internal lints
|
#### Internal lints
|
||||||
|
|
||||||
Note, these include both rustc-internal lints, and the traditional lints, like, for example the dead
|
These are lints used just by the compiler or plugins like `clippy`. They can be found in
|
||||||
code lint.
|
`rustc_lint::internal`.
|
||||||
|
|
||||||
|
An example of such a lint is the check that lint passes are implemented using the `declare_lint_pass!`
|
||||||
|
macro and not by hand. This is accomplished with the `LINT_PASS_IMPL_WITHOUT_MACRO` lint.
|
||||||
|
|
||||||
|
Registration of these lints happens in the [`rustc_lint::register_internals`] function which is
|
||||||
|
called when constructing a new lint store inside [`rustc_lint::new_lint_store`].
|
||||||
|
|
||||||
|
### Builtin Lints
|
||||||
|
|
||||||
These are primarily described in two places: `rustc_session::lint::builtin` and
|
These are primarily described in two places: `rustc_session::lint::builtin` and
|
||||||
`rustc_lint::builtin`. The first provides the definitions for the lints themselves,
|
`rustc_lint::builtin`. Often the first provides the definitions for the lints themselves,
|
||||||
and the latter provides the lint pass definitions (and implementations).
|
and the latter provides the lint pass definitions (and implementations), but this is not always
|
||||||
|
true.
|
||||||
|
|
||||||
The internal lint registration happens in the [`rustc_lint::register_builtins`] function, along with
|
The builtin lint registration happens in the [`rustc_lint::register_builtins`] function. Just like
|
||||||
the [`rustc_lint::register_internals`] function. More generally, the LintStore "constructor"
|
with internal lints, this happens inside of [`rustc_lint::new_lint_store`].
|
||||||
function which is *the* way to get a `LintStore` in the compiler (you should not construct it
|
|
||||||
directly) is [`rustc_lint::new_lint_store`]; it calls the registration functions.
|
|
||||||
|
|
||||||
#### Plugin lints
|
#### Plugin lints
|
||||||
|
|
||||||
This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the
|
This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the
|
||||||
mutable `LintStore` during registration to call any functions they need on the `LintStore`, just
|
mutable `LintStore` during registration (which happens inside of [`rustc_interface::register_plugins`])
|
||||||
like rustc code. Plugins are intended to declare lints with the `plugin` field set to true (e.g., by
|
and they can call any functions they need on the `LintStore`, just like rustc code.
|
||||||
|
|
||||||
|
Plugins are intended to declare lints with the `plugin` field set to true (e.g., by
|
||||||
way of the [`declare_tool_lint!`] macro), but this is purely for diagnostics and help text;
|
way of the [`declare_tool_lint!`] macro), but this is purely for diagnostics and help text;
|
||||||
otherwise plugin lints are mostly just as first class as rustc builtin lints.
|
otherwise plugin lints are mostly just as first class as rustc builtin lints.
|
||||||
|
|
||||||
|
|
@ -86,18 +96,15 @@ within the callback they add. The best way for drivers to get access to this is
|
||||||
|
|
||||||
Within the compiler, for performance reasons, we usually do not register dozens
|
Within the compiler, for performance reasons, we usually do not register dozens
|
||||||
of lint passes. Instead, we have a single lint pass of each variety
|
of lint passes. Instead, we have a single lint pass of each variety
|
||||||
(e.g. `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
|
(e.g., `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
|
||||||
individual lint passes; this is because then we get the benefits of static over
|
individual lint passes; this is because then we get the benefits of static over
|
||||||
dynamic dispatch for each of the (often empty) trait methods.
|
dynamic dispatch for each of the (often empty) trait methods.
|
||||||
|
|
||||||
Ideally, we'd not have to do this, since it certainly adds to the complexity of
|
Ideally, we'd not have to do this, since it adds to the complexity of
|
||||||
understanding the code. However, with the current type-erased lint store
|
understanding the code. However, with the current type-erased lint store
|
||||||
approach, it is beneficial to do so for performance reasons.
|
approach, it is beneficial to do so for performance reasons.
|
||||||
|
|
||||||
New lints being added likely want to join one of the existing declarations like
|
[`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html
|
||||||
`late_lint_mod_passes` in `rustc_lint/src/lib.rs`, which would then
|
|
||||||
auto-propagate into the other.
|
|
||||||
|
|
||||||
[`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_lints
|
[`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_lints
|
||||||
[`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html
|
[`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html
|
||||||
[`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html
|
[`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue