Merge pull request #2465 from xizheyin/rustc-query

Adjust some doc for Query System
This commit is contained in:
Tshepang Mbambo 2025-06-14 21:39:25 +02:00 committed by GitHub
commit 91ede12d31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 66 additions and 59 deletions

View File

@ -67,9 +67,15 @@ are cheaply cloneable; insert an `Rc` if necessary).
### Providers ### Providers
If, however, the query is *not* in the cache, then the compiler will If, however, the query is *not* in the cache, then the compiler will
try to find a suitable **provider**. A provider is a function that has call the corresponding **provider** function. A provider is a function
been defined and linked into the compiler somewhere that contains the implemented in a specific module and **manually registered** into the
code to compute the result of the query. [`Providers`][providers_struct] struct during compiler initialization.
The macro system generates the [`Providers`][providers_struct] struct,
which acts as a function table for all query implementations, where each
field is a function pointer to the actual provider.
**Note:** The `Providers` struct is generated by macros and acts as a function table for all query implementations.
It is **not** a Rust trait, but a plain struct with function pointer fields.
**Providers are defined per-crate.** The compiler maintains, **Providers are defined per-crate.** The compiler maintains,
internally, a table of providers for every crate, at least internally, a table of providers for every crate, at least
@ -97,6 +103,17 @@ fn provider<'tcx>(
Providers take two arguments: the `tcx` and the query key. Providers take two arguments: the `tcx` and the query key.
They return the result of the query. They return the result of the query.
N.B. Most of the `rustc_*` crates only provide **local
providers**. Almost all **extern providers** wind up going through the
[`rustc_metadata` crate][rustc_metadata], which loads the information
from the crate metadata. But in some cases there are crates that
provide queries for *both* local and external crates, in which case
they define both a `provide` and a `provide_extern` function, through
[`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke.
[rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
[wasm_import_module_map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/symbol_export/fn.wasm_import_module_map.html
### How providers are set up ### How providers are set up
When the tcx is created, it is given the providers by its creator using When the tcx is created, it is given the providers by its creator using
@ -108,19 +125,16 @@ the macros here, but it is basically a big list of function pointers:
```rust,ignore ```rust,ignore
struct Providers { struct Providers {
type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>, type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>,
... // ... one field for each query
} }
``` ```
At present, we have one copy of the struct for local crates, and one #### How are providers registered?
for external crates, though the plan is that we may eventually have
one per crate.
These `Providers` structs are ultimately created and populated by The `Providers` struct is filled in during compiler initialization, mainly by the `rustc_driver` crate.
`rustc_driver`, but it does this by distributing the work But the actual provider functions are implemented in various `rustc_*` crates (like `rustc_middle`, `rustc_hir_analysis`, etc).
throughout the other `rustc_*` crates. This is done by invoking
various [`provide`][provide_fn] functions. These functions tend to look To register providers, each crate exposes a [`provide`][provide_fn] function that looks like this:
something like this:
[provide_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html [provide_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html
@ -128,41 +142,34 @@ something like this:
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
*providers = Providers { *providers = Providers {
type_of, type_of,
// ... add more providers here
..*providers ..*providers
}; };
} }
``` ```
That is, they take an `&mut Providers` and mutate it in place. Usually - This function takes a mutable reference to the `Providers` struct and sets the fields to point to the correct provider functions.
we use the formulation above just because it looks nice, but you could - You can also assign fields individually, e.g. `providers.type_of = type_of;`.
as well do `providers.type_of = type_of`, which would be equivalent.
(Here, `type_of` would be a top-level function, defined as we saw
before.) So, if we want to add a provider for some other query,
let's call it `fubar`, into the crate above, we might modify the `provide()`
function like so:
#### Adding a new provider
Suppose you want to add a new query called `fubar`. You would:
1. Implement the provider function:
```rust,ignore
fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
```
2. Register it in the `provide` function:
```rust,ignore ```rust,ignore
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
*providers = Providers { *providers = Providers {
type_of,
fubar, fubar,
..*providers ..*providers
}; };
} }
fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
``` ```
N.B. Most of the `rustc_*` crates only provide **local ---
providers**. Almost all **extern providers** wind up going through the
[`rustc_metadata` crate][rustc_metadata], which loads the information
from the crate metadata. But in some cases there are crates that
provide queries for *both* local and external crates, in which case
they define both a `provide` and a `provide_extern` function, through
[`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke.
[rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
[wasm_import_module_map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/symbol_export/fn.wasm_import_module_map.html
## Adding a new query ## Adding a new query