Skip to content

Commit 110076d

Browse files
committed
Refinement of Providers into Providers and ExternProviders
Signed-off-by: xizheyin <[email protected]>
1 parent 5975693 commit 110076d

File tree

1 file changed

+37
-34
lines changed

1 file changed

+37
-34
lines changed

src/query.md

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,24 @@ are cheaply cloneable; insert an `Rc` if necessary).
7171

7272
If, however, the query is *not* in the cache, then the compiler will
7373
call the corresponding **provider** function. A provider is a function
74-
implemented in a specific module and **manually registered** into the
75-
[`Providers`][providers_struct] struct during compiler initialization.
76-
The macro system generates the [`Providers`][providers_struct] struct,
77-
which acts as a function table for all query implementations, where each
74+
implemented in a specific module and **manually registered** into either
75+
the [`Providers`][providers_struct] struct (for local crate queries) or
76+
the [`ExternProviders`][extern_providers_struct] struct (for external crate queries)
77+
during compiler initialization. The macro system generates both structs,
78+
which act as function tables for all query implementations, where each
7879
field is a function pointer to the actual provider.
7980

80-
**Note:** The `Providers` struct is generated by macros and acts as a function table for all query implementations.
81-
It is **not** a Rust trait, but a plain struct with function pointer fields.
81+
**Note:** Both the `Providers` and `ExternProviders` structs are generated by macros and act as function tables for all query implementations.
82+
They are **not** Rust traits, but plain structs with function pointer fields.
8283

8384
**Providers are defined per-crate.** The compiler maintains,
8485
internally, a table of providers for every crate, at least
85-
conceptually. Right now, there are really two sets: the providers for
86-
queries about the **local crate** (that is, the one being compiled)
87-
and providers for queries about **external crates** (that is,
88-
dependencies of the local crate). Note that what determines the crate
89-
that a query is targeting is not the *kind* of query, but the *key*.
86+
conceptually. There are two sets of providers:
87+
- The `Providers` struct for queries about the **local crate** (that is, the one being compiled)
88+
- The `ExternProviders` struct for queries about **external crates** (that is,
89+
dependencies of the local crate)
90+
91+
Note that what determines the crate that a query is targeting is not the *kind* of query, but the *key*.
9092
For example, when you invoke `tcx.type_of(def_id)`, that could be a
9193
local query or an external query, depending on what crate the `def_id`
9294
is referring to (see the [`self::keys::Key`][Key] trait for more
@@ -119,40 +121,43 @@ they define both a `provide` and a `provide_extern` function, through
119121

120122
### How providers are set up
121123

122-
When the tcx is created, it is given the providers by its creator using
123-
the [`Providers`][providers_struct] struct. This struct is generated by
124-
the macros here, but it is basically a big list of function pointers:
125-
126-
[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.Providers.html
124+
When the tcx is created, it is given both the local and external providers by its creator using
125+
the `Providers` struct from `rustc_middle::util`. This struct contains both the local and external providers:
127126

128127
```rust,ignore
129-
struct Providers {
130-
type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>,
131-
// ... one field for each query
128+
pub struct Providers {
129+
pub queries: crate::query::Providers, // Local crate providers
130+
pub extern_queries: crate::query::ExternProviders, // External crate providers
131+
pub hooks: crate::hooks::Providers,
132132
}
133133
```
134134

135+
Each of these provider structs is generated by the macros and contains function pointers for their respective queries.
136+
135137
#### How are providers registered?
136138

137-
The `Providers` struct is filled in during compiler initialization, mainly by the `rustc_driver` crate.
139+
The provider structs are filled in during compiler initialization, mainly by the `rustc_driver` crate.
138140
But the actual provider functions are implemented in various `rustc_*` crates (like `rustc_middle`, `rustc_hir_analysis`, etc).
139141

140142
To register providers, each crate exposes a [`provide`][provide_fn] function that looks like this:
141143

142144
[provide_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html
143145

144146
```rust,ignore
145-
pub fn provide(providers: &mut Providers) {
146-
*providers = Providers {
147-
type_of,
148-
// ... add more providers here
149-
..*providers
150-
};
147+
pub fn provide(providers: &mut rustc_middle::util::Providers) {
148+
providers.queries.type_of = type_of;
149+
// ... add more local providers here
150+
151+
providers.extern_queries.type_of = extern_type_of;
152+
// ... add more external providers here
153+
154+
providers.hooks.some_hook = some_hook;
155+
// ... add more hooks here
151156
}
152157
```
153158

154159
- This function takes a mutable reference to the `Providers` struct and sets the fields to point to the correct provider functions.
155-
- You can also assign fields individually, e.g. `providers.type_of = type_of;`.
160+
- You can assign fields individually for each provider type (local, external, and hooks).
156161

157162
#### Adding a new provider
158163

@@ -164,11 +169,10 @@ Suppose you want to add a new query called `fubar`. You would:
164169
```
165170
2. Register it in the `provide` function:
166171
```rust,ignore
167-
pub fn provide(providers: &mut Providers) {
168-
*providers = Providers {
169-
fubar,
170-
..*providers
171-
};
172+
pub fn provide(providers: &mut rustc_middle::util::Providers) {
173+
providers.queries.fubar = fubar;
174+
// If you need an external provider:
175+
providers.extern_queries.fubar = extern_fubar;
172176
}
173177
```
174178
@@ -264,5 +268,4 @@ More discussion and issues:
264268
["Red/Green" dependency tracking in compiler]: https://github.com/rust-lang/rust/issues/42293
265269
[GitHub issue #42633]: https://github.com/rust-lang/rust/issues/42633
266270
[Incremental Compilation Beta]: https://internals.rust-lang.org/t/incremental-compilation-beta/4721
267-
[Incremental Compilation Announcement]: https://blog.rust-lang.org/2016/09/08/incremental.html
268-
271+
[Incremental Compilation Announcement]: https://blog.rust-lang.org/2016/09/08/incremental.html

0 commit comments

Comments
 (0)