Home Explore Blog CI



rustc

3rd chunk of `src/query.md`
aefbd9cff6e995294e47ed8a22d3bfa2e653cdfa58a27c100000000100000f07
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]



Title: Adding New Queries: Definition, Declaration, and Linking
Summary
Adding a new query involves declaring its name, arguments, and description in `compiler/rustc_middle/src/query/mod.rs` using the `rustc_queries!` macro. A user-facing description using the `desc` attribute is important for displaying cycle errors. The query definition includes the 'query' keyword, the query name, key type, result type, and modifiers. Finally, the provider must be linked by modifying an existing `provide` method or creating a new one and ensuring `rustc_driver` invokes it. Most local providers are in the `rustc_*` crates, extern providers use `rustc_metadata` crate, loading from crate metadata. Some crates provide for both local and external, defining both a `provide` and a `provide_extern` function.