@@ -71,22 +71,24 @@ are cheaply cloneable; insert an `Rc` if necessary).
71
71
72
72
If, however, the query is * not* in the cache, then the compiler will
73
73
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
78
79
field is a function pointer to the actual provider.
79
80
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.
82
83
83
84
** Providers are defined per-crate.** The compiler maintains,
84
85
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* .
90
92
For example, when you invoke ` tcx.type_of(def_id) ` , that could be a
91
93
local query or an external query, depending on what crate the ` def_id `
92
94
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
119
121
120
122
### How providers are set up
121
123
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:
127
126
128
127
``` 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,
132
132
}
133
133
```
134
134
135
+ Each of these provider structs is generated by the macros and contains function pointers for their respective queries.
136
+
135
137
#### How are providers registered?
136
138
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.
138
140
But the actual provider functions are implemented in various ` rustc_* ` crates (like ` rustc_middle ` , ` rustc_hir_analysis ` , etc).
139
141
140
142
To register providers, each crate exposes a [ ` provide ` ] [ provide_fn ] function that looks like this:
141
143
142
144
[ provide_fn ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html
143
145
144
146
``` 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
151
156
}
152
157
```
153
158
154
159
- 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) .
156
161
157
162
#### Adding a new provider
158
163
@@ -164,11 +169,10 @@ Suppose you want to add a new query called `fubar`. You would:
164
169
```
165
170
2. Register it in the `provide` function:
166
171
```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;
172
176
}
173
177
```
174
178
@@ -264,5 +268,4 @@ More discussion and issues:
264
268
[ "Red/Green" dependency tracking in compiler ] : https://github.com/rust-lang/rust/issues/42293
265
269
[ GitHub issue #42633 ] : https://github.com/rust-lang/rust/issues/42633
266
270
[ 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