@@ -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