Home Explore Blog CI



rustc

3rd chunk of `src/queries/query-evaluation-model-in-detail.md`
9d632b11e4bcc6ee3d6b1838693833eab57ef8eba92460710000000100000830
        tcx.type_check_item(item_def_id);
    }
}
```

We see that the `type_check_crate` query accesses input data
(`tcx.hir_map.list_of_items()`) and invokes other queries
(`type_check_item`). The `type_check_item`
invocations will themselves access input data and/or invoke other queries,
so that in the end the DAG of query invocations will be built up backwards
from the node that was initially executed:

```ignore
         (2)                                                 (1)
  list_of_all_hir_items <----------------------------- type_check_crate()
                                                               |
    (5)             (4)                  (3)                   |
  Hir(foo) <--- type_of(foo) <--- type_check_item(foo) <-------+
                                      |                        |
                    +-----------------+                        |
                    |                                          |
    (7)             v  (6)                  (8)                |
  Hir(bar) <--- type_of(bar) <--- type_check_item(bar) <-------+

// (x) denotes invocation order
```

We also see that often a query result can be read from the cache:
`type_of(bar)` was computed for `type_check_item(foo)` so when
`type_check_item(bar)` needs it, it is already in the cache.

Query results stay cached in the query context as long as the context lives.
So if the compiler driver invoked another query later on, the above graph
would still exist and already executed queries would not have to be re-done.



## Cycles

Earlier we stated that query invocations form a DAG. However, it would be easy
to form a cyclic graph by, for example, having a query provider like the
following:

```rust,ignore
fn cyclic_query_provider(tcx, key) -> u32 {
  // Invoke the same query with the same key again
  tcx.cyclic_query(key)
}
```

Since query providers are regular functions, this would behave much as expected:
Evaluation would get stuck in an infinite recursion. A query like this would not
be very useful either. However, sometimes certain kinds of invalid user input

Title: Example of Query Execution and Caching, Cycles in Queries
Summary
An example elaborates on how queries are executed and cached within the query context. The `type_check_crate` query accesses input data and invokes `type_check_item` queries, creating a directed acyclic graph (DAG) of query invocations. Query results are cached for the lifetime of the context, avoiding recomputation if the same query is invoked again later. The example also addresses the possibility of forming cycles in query invocations, which would lead to infinite recursion and are generally avoided, but they might occur because of invalid user input.