---
# System prepended metadata

title: Injecting query results

---

# Injecting query results

* [WIP PR](https://github.com/rust-lang/rust/pull/96840)


## High level desired feature

We would like to be able to fill in the result-cache of a query `X` while computing another query `Y`. This is important if `X` depends on `Y`, but to compute `Y` we need a (part) of `X`. To break such cycles, we could not call `Y` at all from `X`, but compute `Y`'s value within `X`. From the outside this effectively makes computing `X` magically "compute" `Y`, too.

## What the PR does

The PR allows a query `Y` to feed a value `x` as the output of query `X`. The dependencies of `X` are set as the recorded dependencies of `Y` up to the moment the value is fed.

The PR introduces several checks around the feeding:
1. If there is already a value in cache, we check for equality;
2. If the `DepNode` for `X` is already green, we check that `x`'s fingerprint matches the `DepNode`'s.
3. If a "regular" query call to `X` completes after we fed `x` in cache, we check that the fingerprints match (this may happen if computing `X` calls `Y` which sets `X := x`).

## Issues with the PRs feature

We need to limit is so that you cannot "feed" a value from one query to another *unless* the first query created the key used by the second query. Otherwise, you run the very real risk of non-deterministic results if the query order changes. 

The danger is something like this:

* Query A(X) sets the result of B(X).
* Query C(X) reads B(X).
* Query D(X) first executes A(X) and then C(X).

Now if you start by invoking `C`, you get one value (whatever `B(X)` computes).

But if you start by invoking `D`, you get a different value (whatever `A(X)` stored).

The PR works by setting the "inputs" for `B(X)` to be the inputs that `A(X)` has observed thus far, but that's not enough to prevent the above problem. While this works for the `typeck` <-> `typeof(anon_const)` cycle and is sound (says @oli-obk), it would be a footgun to leave it like that as other queries will definitely cause problems.

Fingerprint check #1 will detect the `C` then `D` case, and ICE in case of inconsistency. In the `D` then `C` case, `B` won't be computed.

## More salsa-like scheme

One way for making this robust is to have [TyCtxt::create_def](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.create_def) return a `NewDefId` wrapper type that can only be created by `create_def`. Then `tcx.feed().query_name` would only accept arguments of type `NewDefId` where they currently require `DefId`. You can always `NewDefId::into_inner` to use it normally, but for feeding you'll need the `NewDefId`. Then we just need to make sure no one returns `NewDefId` from a query, but that seems doable (just implement no traits at all for it).

For this PR that would mean to stop generating `DefId`s for `AnonConst` in AST->HIR lowering and instead leave that to typeck of the owner of the anon const.

Delaying the creation of the `DefId` after HIR creates an inconsistency in HIR-based `HirId <-> LocalDefId` bidirectional map.
The `LocalDefId -> HirId` mapping can be amended by feeding the query `local_def_id_to_hir_id(NewDefId) := anon_const.hir_id`.
The `HirId -> LocalDefId` mapping cannot be modified because another query might have relied on `tcx.hir().opt_local_def_id(anon_const.hir_id)` being `None`.

# Question/Topic Queue

## What is cost of not doing this?

pnkfelix: From reading the description, I am assuming that if we do not add this feature, then the main cost is that instead of structuring things with just two queries X and Y, one would have to instead break the query X up into two pieces, X1 and X2, such that the stuff from X that depends on Y now lives in X2, and the stuff in X that was used to compute Y now lives in X1, so that you end up with a dependence graph like the following?

```
X2 -> X1
X2 -> Y
Y -> X1
```

cjgillot: that's one way to do it.  The other way is what we have right now: `WithOptConstParam`, ie. piggy-back the required information to the dependents of `X` so they do not depend on `Y`.

## Queries that are only provided by another query

wesleywiser: The situation described above where query A sometimes provides the result of query B seems to imply that query B has its own implementation. Would it be practical for query B to not have an implementation and soley rely on query A to provide the appropriate results? 

That would remove the possibilty of queries being called in a different order and seeing different results causing non-determinism. I think it would also prevent the implementations of query A and query B from diverging and causing different results depending on if query A provided query B's result or if query B itself was executed to compute the result. 


