@@ -67,9 +67,15 @@ are cheaply cloneable; insert an `Rc` if necessary).
67
67
### Providers
68
68
69
69
If, however, the query is * not* in the cache, then the compiler will
70
- try to find a suitable ** provider** . A provider is a function that has
71
- been defined and linked into the compiler somewhere that contains the
72
- code to compute the result of the query.
70
+ call the corresponding ** provider** function. A provider is a function
71
+ implemented in a specific module and ** manually registered** into the
72
+ [ ` Providers ` ] [ providers_struct ] struct during compiler initialization.
73
+ The macro system generates the [ ` Providers ` ] [ providers_struct ] struct,
74
+ which acts as a function table for all query implementations, where each
75
+ field is a function pointer to the actual provider.
76
+
77
+ ** Note:** The ` Providers ` struct is generated by macros and acts as a function table for all query implementations.
78
+ It is ** not** a Rust trait, but a plain struct with function pointer fields.
73
79
74
80
** Providers are defined per-crate.** The compiler maintains,
75
81
internally, a table of providers for every crate, at least
@@ -97,7 +103,18 @@ fn provider<'tcx>(
97
103
Providers take two arguments: the ` tcx ` and the query key.
98
104
They return the result of the query.
99
105
100
- ### How providers are setup
106
+ N.B. Most of the ` rustc_* ` crates only provide ** local
107
+ providers** . Almost all ** extern providers** wind up going through the
108
+ [ ` rustc_metadata ` crate] [ rustc_metadata ] , which loads the information
109
+ from the crate metadata. But in some cases there are crates that
110
+ provide queries for * both* local and external crates, in which case
111
+ they define both a ` provide ` and a ` provide_extern ` function, through
112
+ [ ` wasm_import_module_map ` ] [ wasm_import_module_map ] , that ` rustc_driver ` can invoke.
113
+
114
+ [ rustc_metadata ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
115
+ [ wasm_import_module_map ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/symbol_export/fn.wasm_import_module_map.html
116
+
117
+ ### How providers are set up
101
118
102
119
When the tcx is created, it is given the providers by its creator using
103
120
the [ ` Providers ` ] [ providers_struct ] struct. This struct is generated by
@@ -108,61 +125,51 @@ the macros here, but it is basically a big list of function pointers:
108
125
``` rust,ignore
109
126
struct Providers {
110
127
type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>,
111
- ...
128
+ // ... one field for each query
112
129
}
113
130
```
114
131
115
- At present, we have one copy of the struct for local crates, and one
116
- for external crates, though the plan is that we may eventually have
117
- one per crate.
132
+ #### How are providers registered?
133
+
134
+ The ` Providers ` struct is filled in during compiler initialization, mainly by the ` rustc_driver ` crate.
135
+ But the actual provider functions are implemented in various ` rustc_* ` crates (like ` rustc_middle ` , ` rustc_hir_analysis ` , etc).
118
136
119
- These ` Providers ` structs are ultimately created and populated by
120
- ` rustc_driver ` , but it does this by distributing the work
121
- throughout the other ` rustc_* ` crates. This is done by invoking
122
- various [ ` provide ` ] [ provide_fn ] functions. These functions tend to look
123
- something like this:
137
+ To register providers, each crate exposes a [ ` provide ` ] [ provide_fn ] function that looks like this:
124
138
125
139
[ provide_fn ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html
126
140
127
141
``` rust,ignore
128
142
pub fn provide(providers: &mut Providers) {
129
143
*providers = Providers {
130
144
type_of,
145
+ // ... add more providers here
131
146
..*providers
132
147
};
133
148
}
134
149
```
135
150
136
- That is, they take an ` &mut Providers ` and mutate it in place. Usually
137
- we use the formulation above just because it looks nice, but you could
138
- as well do ` providers.type_of = type_of ` , which would be equivalent.
139
- (Here, ` type_of ` would be a top-level function, defined as we saw
140
- before.) So, if we want to add a provider for some other query,
141
- let's call it ` fubar ` , into the crate above, we might modify the ` provide() `
142
- function like so:
151
+ - This function takes a mutable reference to the ` Providers ` struct and sets the fields to point to the correct provider functions.
152
+ - You can also assign fields individually, e.g. ` providers.type_of = type_of; ` .
143
153
144
- ``` rust,ignore
145
- pub fn provide(providers: &mut Providers) {
146
- *providers = Providers {
147
- type_of,
148
- fubar,
149
- ..*providers
150
- };
151
- }
154
+ #### Adding a new provider
152
155
153
- fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
154
- ```
156
+ Suppose you want to add a new query called ` fubar ` . You would:
155
157
156
- N.B. Most of the ` rustc_* ` crates only provide ** local
157
- providers** . Almost all ** extern providers** wind up going through the
158
- [ ` rustc_metadata ` crate] [ rustc_metadata ] , which loads the information
159
- from the crate metadata. But in some cases there are crates that
160
- provide queries for * both* local and external crates, in which case
161
- they define both a ` provide ` and a ` provide_extern ` function, through
162
- [ ` wasm_import_module_map ` ] [ wasm_import_module_map ] , that ` rustc_driver ` can invoke.
158
+ 1 . Implement the provider function:
159
+ ``` rust,ignore
160
+ fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
161
+ ```
162
+ 2. Register it in the `provide` function:
163
+ ```rust,ignore
164
+ pub fn provide(providers: &mut Providers) {
165
+ *providers = Providers {
166
+ fubar,
167
+ ..*providers
168
+ };
169
+ }
170
+ ```
163
171
164
- [ rustc_metadata ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
165
- [ wasm_import_module_map ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/symbol_export/fn.wasm_import_module_map.html
172
+ ---
166
173
167
174
## Adding a new query
168
175
0 commit comments