Refine the lintstore section (#1429)

This commit is contained in:
Tshepang Mbambo 2022-08-27 07:59:56 +02:00 committed by GitHub
parent daca4683bb
commit b5a632f462
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 32 additions and 13 deletions

View File

@ -1,4 +1,5 @@
# Lints # Lints
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.
@ -8,6 +9,7 @@ everything rotates. It's not available during the early parts of compilation
lints, which can only happen after plugin registration. lints, which can only happen after plugin registration.
## Lints vs. lint passes ## Lints vs. lint passes
There are two parts to the linting mechanism within the compiler: lints and There are two parts to the linting mechanism within the compiler: lints and
lint passes. Unfortunately, a lot of the documentation we have refers to both lint passes. Unfortunately, a lot of the documentation we have refers to both
of these as just "lints." of these as just "lints."
@ -15,11 +17,18 @@ of these as just "lints."
First, we have the lint declarations themselves: this is where the name and First, we have the lint declarations themselves: this is where the name and
default lint level and other metadata come from. These are normally defined by default lint level and other metadata come from. These are normally defined by
way of the [`declare_lint!`] macro, which boils down to a static with type way of the [`declare_lint!`] macro, which boils down to a static with type
`&rustc_session::lint::Lint`. [`&rustc_lint_defs::Lint`].
As of <!-- date-check --> February 2022, we lint against direct declarations First, we have the lint declarations themselves,
without the use of the macro today (although this may change in the future, as and this is where the name and default lint level and other metadata come from.
the macro is somewhat unwieldy to add new fields to, like all macros). These are normally defined by way of the [`declare_lint!`] macro,
which boils down to a static with type [`&rustc_lint_defs::Lint`]
(although this may change in the future,
as the macro is somewhat unwieldy to add new fields to,
like all macros).
As of <!-- date-check --> Aug 2022,
we lint against direct declarations without the use of the macro.
Lint declarations don't carry any "state" - they are merely global identifiers Lint declarations don't carry any "state" - they are merely global identifiers
and descriptions of lints. We assert at runtime that they are not registered and descriptions of lints. We assert at runtime that they are not registered
@ -34,8 +43,10 @@ lints are emitted as part of other work (e.g., type checking, etc.).
## Registration ## Registration
### High-level overview ### High-level overview
In [`rustc_interface::register_plugins`] the [`LintStore`] is created and all
lints are registered. In [`rustc_interface::register_plugins`],
the [`LintStore`] is created,
and all lints are registered.
There are four 'sources' of lints: There are four 'sources' of lints:
@ -61,6 +72,7 @@ then invoke the lint pass methods. The lint pass methods take `&mut self` so
they can keep track of state internally. they can keep track of state internally.
#### Internal lints #### Internal lints
These are lints used just by the compiler or plugins like `clippy`. They can be These are lints used just by the compiler or plugins like `clippy`. They can be
found in `rustc_lint::internal`. found in `rustc_lint::internal`.
@ -73,16 +85,20 @@ function which is called when constructing a new lint store inside
[`rustc_lint::new_lint_store`]. [`rustc_lint::new_lint_store`].
### Builtin Lints ### Builtin Lints
These are primarily described in two places: `rustc_session::lint::builtin` and
`rustc_lint::builtin`. Often the first provides the definitions for the lints
themselves, and the latter provides the lint pass definitions (and
implementations), but this is not always true.
The builtin lint registration happens in the [`rustc_lint::register_builtins`] These are primarily described in two places,
function. Just like with internal lints, this happens inside of `rustc_lint_defs::builtin` and `rustc_lint::builtin`.
[`rustc_lint::new_lint_store`]. Often the first provides the definitions for the lints themselves,
and the latter provides the lint pass definitions (and implementations),
but this is not always true.
The builtin lint registration happens in
the [`rustc_lint::register_builtins`] function.
Just like with internal lints,
this happens inside of [`rustc_lint::new_lint_store`].
#### Plugin lints #### Plugin lints
This is one of the primary use cases remaining for plugins/drivers. Plugins are This is one of the primary use cases remaining for plugins/drivers. Plugins are
given access to the mutable `LintStore` during registration (which happens given access to the mutable `LintStore` during registration (which happens
inside of [`rustc_interface::register_plugins`]) and they can call any inside of [`rustc_interface::register_plugins`]) and they can call any
@ -94,6 +110,7 @@ diagnostics and help text; otherwise plugin lints are mostly just as first
class as rustc builtin lints. class as rustc builtin lints.
#### Driver lints #### Driver lints
These are the lints provided by drivers via the `rustc_interface::Config` These are the lints provided by drivers via the `rustc_interface::Config`
[`register_lints`] field, which is a callback. Drivers should, if finding it [`register_lints`] field, which is a callback. Drivers should, if finding it
already set, call the function currently set within the callback they add. The already set, call the function currently set within the callback they add. The
@ -102,6 +119,7 @@ best way for drivers to get access to this is by overriding the
structure. structure.
## Compiler lint passes are combined into one pass ## Compiler lint passes are combined into one pass
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 (e.g., of lint passes. Instead, we have a single lint pass of each variety (e.g.,
`BuiltinCombinedModuleLateLintPass`) which will internally call all of the `BuiltinCombinedModuleLateLintPass`) which will internally call all of the
@ -121,3 +139,4 @@ approach, it is beneficial to do so for performance reasons.
[`declare_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_lint.html [`declare_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_lint.html
[`declare_tool_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_tool_lint.html [`declare_tool_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_tool_lint.html
[`register_lints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html#structfield.register_lints [`register_lints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html#structfield.register_lints
[`&rustc_lint_defs::Lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/struct.Lint.html