This page describes the central infrastructure that all compiler phases share: the TyCtxt type context, the demand-driven query system, and the interning mechanism for types, regions, and constants. Together these components form the backbone of rustc_middle, the crate that all other compiler crates depend on.
For information about how the compilation pipeline invokes queries in specific phases (type checking, borrow checking, etc.), see pages 2.5 and 2.6. For metadata encoding/decoding that uses query results, see 3.3. For the diagnostic system that TyCtxt carries a handle to, see 3.2.
TyCtxt<'tcx> is the single most pervasive type in the compiler. It is Copy and acts as a thin, cheap-to-pass-around pointer to GlobalCtxt<'tcx>, which owns all the real data.
TyCtxt<'tcx> = &'tcx GlobalCtxt<'tcx> (via Deref)
TyCtxt is implemented as a newtype around a raw reference compiler/rustc_middle/src/ty/context.rs738-743 dereferencing to &'tcx GlobalCtxt<'tcx> compiler/rustc_middle/src/ty/context.rs755-761 All operations on types, queries, and sessions go through methods on TyCtxt.
GlobalCtxt<'tcx> owns the compiler's entire type-level state compiler/rustc_middle/src/ty/context.rs764-836:
| Field | Type | Purpose |
|---|---|---|
arena | &'tcx WorkerLocal<Arena<'tcx>> | Allocator for all 'tcx-lifetime type data |
hir_arena | &'tcx WorkerLocal<hir::Arena<'tcx>> | Allocator for HIR nodes |
interners | CtxtInterners<'tcx> | Hash-consing tables for types, regions, consts |
sess | &'tcx Session | Compilation session (flags, codemap, etc.) |
dep_graph | DepGraph | Dependency tracking for incremental compilation |
types | CommonTypes<'tcx> | Pre-interned primitive types |
lifetimes | CommonLifetimes<'tcx> | Pre-interned common lifetimes |
consts | CommonConsts<'tcx> | Pre-interned common constants |
query_system | QuerySystem<'tcx> | In-memory query result cache |
selection_cache | SelectionCache<...> | Trait selection result cache |
evaluation_cache | EvaluationCache<...> | Trait evaluation result cache |
alloc_map | interpret::AllocMap<'tcx> | Storage for MIR constant allocations |
Code executes with a TyCtxt by calling GlobalCtxt::enter compiler/rustc_middle/src/ty/context.rs838-861 which installs the GlobalCtxt pointer into thread-local storage via tls::ImplicitCtxt and then invokes the provided closure with a TyCtxt. This means any code running inside that closure can retrieve the current TyCtxt from TLS using ty::tls::with(|tcx| ...).
Structural overview of TyCtxt and GlobalCtxt:
Sources: compiler/rustc_middle/src/ty/context.rs137-168 compiler/rustc_middle/src/ty/context.rs344-424 compiler/rustc_middle/src/ty/context.rs738-861
Ty<'tcx> is the compiler's representation of a type compiler/rustc_middle/src/ty/mod.rs454-458 It is a newtype around Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>> — a pointer to an interned, heap-allocated TyKind with pre-computed flags and a stable hash.
TyKind<'tcx> is a type alias compiler/rustc_middle/src/ty/sty.rs35 for rustc_type_ir::TyKind<TyCtxt<'tcx>>. It is an enum covering every possible Rust type:
| Variant | Meaning |
|---|---|
Bool, Char, Str, Never | Primitive / special types |
Int(IntTy), Uint(UintTy), Float(FloatTy) | Numeric primitives |
Adt(AdtDef, GenericArgsRef) | Structs, enums, unions |
Ref(Region, Ty, Mutability) | Shared and mutable references |
RawPtr(Ty, Mutability) | Raw pointers *const T / *mut T |
Slice(Ty), Array(Ty, Const) | Slice and array types |
Tuple(List<Ty>) | Tuple types |
FnDef(DefId, GenericArgsRef) | Function item type |
FnPtr(PolyFnSig) | Function pointer type |
Closure(DefId, GenericArgsRef) | Closure type |
Coroutine(DefId, GenericArgsRef) | Coroutine (async/gen) type |
Dynamic(ExistentialPredicates, Region, DynKind) | Trait object dyn Trait |
Alias(AliasTyKind, AliasTy) | Type aliases, associated types, opaque types |
Param(ParamTy) | Generic type parameter (T) |
Bound(DebruijnIndex, BoundTy) | Bound type variable inside for<> binders |
Placeholder(PlaceholderType) | Universally quantified type during inference |
Infer(InferTy) | Inference variable (TyVar, IntVar, FloatVar, FreshTy) |
Error(ErrorGuaranteed) | Propagated type error |
Foreign(DefId) | Extern type (extern type Foo) |
Similarly, Region<'tcx> wraps RegionKind<'tcx> and Const<'tcx> wraps ConstKind<'tcx>, following the same interning pattern.
TyKind variants mapped to code entities:
Sources: compiler/rustc_middle/src/ty/mod.rs454-476 compiler/rustc_middle/src/ty/sty.rs35-51 compiler/rustc_type_ir/src/ty_kind.rs1-50
Interning ensures that equal types are represented by identical pointers, enabling O(1) equality checks. The CtxtInterners struct compiler/rustc_middle/src/ty/context.rs137-168 holds one InternedSet per internable entity:
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>
ShardedHashMap partitions entries across multiple shards to reduce lock contention in parallel compilation.
The central function is CtxtInterners::intern_ty compiler/rustc_middle/src/ty/context.rs209-227 The process:
TyKind in the sharded hash map.TypeFlags (which summarizes properties such as whether inference variables or bound variables are present) and a Fingerprint stable hash.WithCachedTypeInfo<TyKind> in the arena.Interned<...> wrapper.Ty(Interned::new_unchecked(...)).The caller-facing API goes through TyCtxt::mk_* methods (e.g., Ty::new_ref, Ty::new_adt, Ty::new_param) defined in sty.rs.
Type interning data flow:
Sources: compiler/rustc_middle/src/ty/context.rs135 compiler/rustc_middle/src/ty/context.rs170-317
Frequently used types, lifetimes, and inference variables are interned once at startup and stored in CommonTypes, CommonLifetimes, and CommonConsts. For example, tcx.types.bool, tcx.types.unit, and tcx.lifetimes.re_static are available without any hash map lookup.
The constants controlling how many values to pre-intern compiler/rustc_middle/src/ty/context.rs323-342:
| Constant | Count | For |
|---|---|---|
NUM_PREINTERNED_TY_VARS | 100 | Infer(TyVar(n)) |
NUM_PREINTERNED_FRESH_TYS | 20 | Infer(FreshTy(n)) |
NUM_PREINTERNED_RE_VARS | 500 | ReVar(RegionVid(n)) |
NUM_PREINTERNED_ANON_BOUND_TYS_V | 20 | Bound(_, Anon) |
These numbers were chosen empirically to match observed intern sizes in large crates.
Sources: compiler/rustc_middle/src/ty/context.rs319-499
The rustc_type_ir crate defines the Interner trait compiler/rustc_type_ir/src/interner.rs19-178 to allow type-system logic to be written generically. TyCtxt<'tcx> implements Interner.
Key associated types of Interner:
| Associated Type | rustc implementation |
|---|---|
Ty | ty::Ty<'tcx> |
Region | ty::Region<'tcx> |
Const | ty::Const<'tcx> |
Predicate | ty::Predicate<'tcx> |
Clause | ty::Clause<'tcx> |
Clauses | ty::Clauses<'tcx> |
GenericArgs | ty::GenericArgsRef<'tcx> |
DefId | hir::def_id::DefId |
Span | rustc_span::Span |
DepNodeIndex | dep_graph::DepNodeIndex |
The Interner trait also requires the implementor to provide methods like mk_canonical_var_kinds, mk_external_constraints, with_global_cache, and with_cached_task, which hook into the compiler's query and caching infrastructure.
Interner trait to TyCtxt implementation mapping:
Sources: compiler/rustc_type_ir/src/interner.rs19-200 compiler/rustc_type_ir/src/inherent.rs1-50
The query system is a demand-driven computation framework: each piece of compiler data is a "query" that is computed once, cached, and re-used. Queries form a DAG; the DepGraph records edges to support incremental recompilation.
Callers invoke a query as a method on TyCtxt, for example:
Each call is routed through generated plumbing that:
QuerySystem).OnDiskCache).Providers.DepNodeIndex in the DepGraph.Query execution flow:
Sources: compiler/rustc_middle/src/query/mod.rs1-33 compiler/rustc_middle/src/query/on_disk_cache.rs1-60
Each crate that implements query logic registers its implementations in a Providers struct. Providers is a struct with one function-pointer field per query. Two sets exist:
The metadata decoder in compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs registers itself as the extern provider for all relevant queries compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs226-260
The QuerySystem<'tcx> (held by GlobalCtxt) contains one cache per query. Cache implementations are defined in compiler/rustc_middle/src/query/caches.rs and include:
| Cache type | Used when |
|---|---|
DefaultCache | Standard key → value mapping |
SingleCache | Query with no key (()) |
VecCache | Indexed by a numeric key |
DefIdCache | Keyed by DefId, common for per-item queries |
OnDiskCache compiler/rustc_middle/src/query/on_disk_cache.rs1-60 serializes query results to disk between compiler invocations. On the next build, results whose DepNode has not changed are loaded from disk rather than recomputed. The stable hash stored inside WithCachedTypeInfo (computed during interning) is used to verify that deserialized types are still valid.
To reduce monomorphization cost, query results stored in the in-memory cache are sometimes "erased" to a type-erased representation compiler/rustc_middle/src/query/erase.rs1-30 This avoids generating a unique cache type for every query return type during codegen of the compiler itself.
DepGraph records which DepNode was being computed when each query was invoked, creating a directed graph of dependencies. On a subsequent compilation:
DepNode's inputs are unchanged (verified by stable hash), its cached result is reused.The dep_graph field of GlobalCtxt is the live DepGraph for the current session compiler/rustc_middle/src/ty/context.rs779
Some queries must have their results provided before the query system begins executing (for example, type_of for anonymous constants to break cycles). The TyCtxtFeed<'tcx, KEY> type compiler/rustc_middle/src/ty/context.rs601-685 enables this:
tcx.create_def(...) returns a TyCtxtFeed<'tcx, LocalDefId>.TyCtxtFeed such as .type_of(value) write the query result directly into the cache, bypassing normal query execution.Feed<'tcx, KEY> is a space-optimised variant that does not carry the TyCtxt pointer.Feeding mechanism:
Sources: compiler/rustc_middle/src/ty/context.rs601-719
Because TyCtxt must be accessible throughout deeply nested formatting and debugging code without being passed explicitly, the compiler installs it in thread-local storage. The tls module compiler/rustc_middle/src/ty/context.rs6 provides:
ImplicitCtxt – holds the active TyCtxt and the current query stack.tls::enter_context – sets ImplicitCtxt for the duration of a closure.tls::with(f) – retrieves the current TyCtxt from TLS and calls f.tls::with_opt(f) – same but returns None outside a TyCtxt context.The CurrentGcx struct compiler/rustc_middle/src/ty/context.rs870-892 provides a separate, coarser mechanism for the deadlock handler to access GlobalCtxt outside of Rayon worker threads, where the TLS variable is not set.
Sources: compiler/rustc_middle/src/ty/context.rs838-892 compiler/rustc_middle/src/ty/structural_impls.rs23-53
| Type | File | Role |
|---|---|---|
TyCtxt<'tcx> | rustc_middle/src/ty/context.rs | Copy handle to the entire compiler context |
GlobalCtxt<'tcx> | rustc_middle/src/ty/context.rs | Owns all arenas, caches, interners |
CtxtInterners<'tcx> | rustc_middle/src/ty/context.rs | Hash-consing tables for all internable types |
CommonTypes<'tcx> | rustc_middle/src/ty/context.rs | Pre-interned primitive types |
TyKind<'tcx> | rustc_type_ir/src/ty_kind.rs | Enum of all Rust type constructors |
Ty<'tcx> | rustc_middle/src/ty/mod.rs | Interned pointer to a TyKind |
WithCachedTypeInfo<T> | rustc_type_ir | Wraps interned value with cached flags/hash |
Interner | rustc_type_ir/src/interner.rs | Abstraction trait implemented by TyCtxt |
QuerySystem<'tcx> | rustc_middle/src/query/plumbing.rs | In-memory query result caches |
Providers | rustc_middle/src/queries.rs | Function pointer table for query implementations |
DepGraph | rustc_middle/src/dep_graph | Query dependency tracking |
OnDiskCache | rustc_middle/src/query/on_disk_cache.rs | Incremental compilation result cache |
TyCtxtFeed<'tcx, KEY> | rustc_middle/src/ty/context.rs | Bootstrap mechanism for pre-feeding query results |
Sources: compiler/rustc_middle/src/ty/context.rs1-100 compiler/rustc_middle/src/ty/mod.rs1-170 compiler/rustc_middle/src/query/mod.rs1-33 compiler/rustc_type_ir/src/interner.rs19-200
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.