@@ -67,9 +67,15 @@ are cheaply cloneable; insert an `Rc` if necessary).
6767### Providers
6868
6969If, 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.
7379
7480** Providers are defined per-crate.** The compiler maintains,
7581internally, a table of providers for every crate, at least
@@ -97,7 +103,18 @@ fn provider<'tcx>(
97103Providers take two arguments: the ` tcx ` and the query key.
98104They return the result of the query.
99105
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
101118
102119When the tcx is created, it is given the providers by its creator using
103120the [ ` 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:
108125``` rust,ignore
109126struct Providers {
110127 type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>,
111- ...
128+ // ... one field for each query
112129}
113130```
114131
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).
118136
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:
124138
125139[ provide_fn ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html
126140
127141``` rust,ignore
128142pub fn provide(providers: &mut Providers) {
129143 *providers = Providers {
130144 type_of,
145+ // ... add more providers here
131146 ..*providers
132147 };
133148}
134149```
135150
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; ` .
143153
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
152155
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:
155157
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+ ```
163171
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+ ---
166173
167174## Adding a new query
168175
0 commit comments