Home Explore Blog CI



rustc

1st chunk of `src/diagnostics/lintstore.md`
1d45d1cd5390aeb647b9e9ca89f2de10b1312b79a91310f000000001000008fe
# Lints

This page documents some of the machinery around lint registration and how we
run lints in the compiler.

The [`LintStore`] is the central piece of infrastructure, around which
everything rotates. The `LintStore` is held as part of the [`Session`], and it
gets populated with the list of lints shortly after the `Session` is created.

## Lints vs. lint passes

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
of these as just "lints."

First, we have the lint declarations themselves,
and this is where the name and 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 [`&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
and descriptions of lints. We assert at runtime that they are not registered
twice (by lint name).

Lint passes are the meat of any lint. Notably, there is not a one-to-one
relationship between lints and lint passes; a lint might not have any lint pass
that emits it, it could have many, or just one -- the compiler doesn't track
whether a pass is in any way associated with a particular lint, and frequently
lints are emitted as part of other work (e.g., type checking, etc.).

## Registration

### High-level overview

In [`rustc_interface::run_compiler`],
the [`LintStore`] is created,
and all lints are registered.

There are three 'sources' of lints:

* internal lints: lints only used by the rustc codebase
* builtin lints: lints built into the compiler and not provided by some outside
  source
  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 `Arc`.

Lint passes are registered separately into one of the categories
(pre-expansion, early, late, late module). Passes are registered as a closure

Title: Linting Mechanism in the Rust Compiler
Summary
This section describes the linting mechanism within the Rust compiler, focusing on the registration and execution of lints. The `LintStore` is the core infrastructure, managing both lint declarations and lint passes. Lint declarations define lint metadata, while lint passes implement the logic for detecting and reporting lint issues. Lints can be internal, builtin, or provided by external sources. The `LintStore` is created and populated during compiler initialization, and lint passes are registered separately into different categories based on their execution timing.