@@ -71,22 +71,24 @@ are cheaply cloneable; insert an `Rc` if necessary).
7171
7272If, however, the query is * not* in the cache, then the compiler will
7373call 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
7879field 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,
8485internally, 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* .
9092For example, when you invoke ` tcx.type_of(def_id) ` , that could be a
9193local query or an external query, depending on what crate the ` def_id `
9294is 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.
138140But the actual provider functions are implemented in various ` rustc_* ` crates (like ` rustc_middle ` , ` rustc_hir_analysis ` , etc).
139141
140142To 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 ```
1651702. 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