as well do `providers.type_of = type_of`, which would be equivalent.
(Here, `type_of` would be a top-level function, defined as we saw
before.) So, if we want to add a provider for some other query,
let's call it `fubar`, into the crate above, we might modify the `provide()`
function like so:
```rust,ignore
pub fn provide(providers: &mut Providers) {
*providers = Providers {
type_of,
fubar,
..*providers
};
}
fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
```
N.B. Most of the `rustc_*` crates only provide **local
providers**. Almost all **extern providers** wind up going through the
[`rustc_metadata` crate][rustc_metadata], which loads the information
from the crate metadata. But in some cases there are crates that
provide queries for *both* local and external crates, in which case
they define both a `provide` and a `provide_extern` function, through
[`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke.
## Adding a new query
How do you add a new query?
Defining a query takes place in two steps:
1. Declare the query name, its arguments and description.
2. Supply query providers where needed.
To declare the query name and arguments, you simply add an entry to
the big macro invocation in [`compiler/rustc_middle/src/query/mod.rs`][query-mod].
Then you need to add a documentation comment to it with some _internal_ description.
Then, provide the `desc` attribute which contains a _user-facing_ description of the query.
The `desc` attribute is shown to the user in query cycles.
This looks something like:
```rust,ignore
rustc_queries! {
/// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> {
cache_on_disk_if { key.is_local() }
desc { |tcx| "computing the type of `{}`", tcx.def_path_str(key) }
}
...
}
```
A query definition has the following form:
```rust,ignore
query type_of(key: DefId) -> Ty<'tcx> { ... }
^^^^^ ^^^^^^^ ^^^^^ ^^^^^^^^ ^^^
| | | | |
| | | | query modifiers
| | | result type
| | query key type
| name of query
query keyword
```
Let's go over these elements one by one:
- **Query keyword:** indicates a start of a query definition.
- **Name of query:** the name of the query method
(`tcx.type_of(..)`). Also used as the name of a struct
(`ty::queries::type_of`) that will be generated to represent
this query.
- **Query key type:** the type of the argument to this query.
This type must implement the [`ty::query::keys::Key`][Key] trait, which
defines (for example) how to map it to a crate, and so forth.
- **Result type of query:** the type produced by this query. This type
should (a) not use `RefCell` or other interior mutability and (b) be
cheaply cloneable. Interning or using `Rc` or `Arc` is recommended for
non-trivial data types.[^steal]
- **Query modifiers:** various flags and options that customize how the
query is processed (mostly with respect to [incremental compilation][incrcomp]).
So, to add a query:
- Add an entry to `rustc_queries!` using the format above.
- Link the provider by modifying the appropriate `provide` method;
or add a new one if needed and ensure that `rustc_driver` is invoking it.
which is used to cheaply modify MIR in place. See the definition
of `Steal` for more details. New uses of `Steal` should **not** be
added without alerting `@rust-lang/compiler`.
## External links
Related design ideas, and tracking issues:
- Design document: [On-demand Rustc incremental design doc]
- Tracking Issue: ["Red/Green" dependency tracking in compiler]
More discussion and issues:
- [GitHub issue #42633]
- [Incremental Compilation Beta]
- [Incremental Compilation Announcement]