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