This page covers the two compiler crates responsible for determining and verifying types: rustc_hir_analysis (type collection, well-formedness, impl checking, HIR type lowering) and rustc_hir_typeck (type inference within function bodies, method resolution, coercions, closure typing, and diagnostic suggestions). This work consumes the HIR produced by AST lowering (see 2.4) and feeds resolved types into MIR building (see 2.6). The query system and type representation internals are described separately in 3.1.
The type system work is split across two crates with a clear division of responsibility:
| Crate | Primary Role | Key Context Type |
|---|---|---|
rustc_hir_analysis | Item-level analysis: signatures, bounds, WF, impl conformance | ItemCtxt (no inference) |
rustc_hir_typeck | Body-level analysis: expression/pattern typing, method lookup | FnCtxt (inference-capable) |
Overall phase ordering (from rustc_hir_analysis/src/lib.rs):
Type Checking Phase Overview
Sources: compiler/rustc_hir_analysis/src/lib.rs1-50 compiler/rustc_hir_typeck/src/lib.rs1-60
rustc_hir_analysis: Item-Level AnalysisThe collect phase computes the inter-procedural type information for every item — function signatures, generic parameters, where-clauses, and ADT layouts — without examining expression bodies.
Key queries registered in collect.rs:
| Query | Function |
|---|---|
type_of | type_of::type_of |
fn_sig | fn_sig |
generics_of | generics_of::generics_of |
predicates_of | predicates_of::predicates_of |
explicit_predicates_of | predicates_of::explicit_predicates_of |
trait_def | trait_def |
adt_def | adt_def |
impl_trait_header | impl_trait_header |
Sources: compiler/rustc_hir_analysis/src/collect.rs60-97
ItemCtxt vs FnCtxtItemCtxt is the lowering context used during collection. It implements HirTyLowerer but has no InferCtxt — it cannot do inference. Its re_infer and ty_infer methods either error or return placeholder types.
FnCtxt (in rustc_hir_typeck) wraps an InferCtxt and is used for body checking where inference variables are needed.
Sources: compiler/rustc_hir_analysis/src/collect.rs102-133 compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs122-205 compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs1-50
HirTyLowerer)The HirTyLowerer trait (compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs126-210) defines the interface for converting HIR type representations (hir::Ty) into the internal ty::Ty type. Key methods:
lower_ty – the main entrypoint for converting a HIR type nodelower_fn_sig – lowers a function declaration's parameter and return typesprobe_ty_param_bounds – resolves T::Assoc shorthand by searching in-scope boundslower_assoc_item_path – lowers an associated type path to a projection typeselect_inherent_assoc_candidates – resolves inherent associated typesThe module contains sub-modules for specialized lowering: bounds, dyn_trait, generics, and errors.
WfCheckingCtxt (compiler/rustc_hir_analysis/src/check/wfcheck.rs48-58) wraps an ObligationCtxt and is the environment for all WF checks. The entrypoint is enter_wf_checking_ctxt which:
InferCtxt in non-body analysis mode&WfCheckingCtxtItems checked by check_item (compiler/rustc_hir_analysis/src/check/wfcheck.rs220-302):
| Item kind | Check performed |
|---|---|
ItemKind::Impl | check_impl_wf, impl coherence, check_impl |
ItemKind::Fn | check_item_fn |
ItemKind::Struct | check_type_defn |
ItemKind::Union | check_type_defn |
ItemKind::Enum | check_type_defn |
ItemKind::Trait | check_trait + check_gat_where_clauses |
check_gat_where_clauses (compiler/rustc_hir_analysis/src/check/wfcheck.rs352-439) ensures Generic Associated Types (GATs) have the necessary where-clauses for their outlives relationships.
Sources: compiler/rustc_hir_analysis/src/check/wfcheck.rs128-203
compare_impl_item (compiler/rustc_hir_analysis/src/check/compare_impl_item.rs37-53) verifies that each item in an impl Trait for T block correctly implements the corresponding trait item. It dispatches to:
compare_impl_method for associated functionscompare_impl_ty for associated typescompare_impl_const for associated constantscompare_impl_method calls check_method_is_structurally_compatible which checks:
compare_self_type – receiver compatibilitycompare_number_of_generics – generic parameter counts matchcompare_number_of_method_arguments – argument counts matchcompare_synthetic_generics – impl Trait in argument positioncheck_region_bounds_on_impl_item – lifetime bound consistencyThen compare_method_predicate_entailment checks that the impl method's bounds are entailed by the trait method's bounds in the appropriate substitution context.
Sources: compiler/rustc_hir_analysis/src/check/compare_impl_item.rs64-92
rustc_hir_typeck: Body-Level Type CheckingFnCtxt and TypeckRootCtxtFnCtxt is the central context for type-checking a single function body. It holds:
TypeckRootCtxt (shared state for the entire body owner)InferCtxt for inference variable management (accessed via Deref)param_env: ParamEnv<'tcx> — the parameter environmentbody_id: LocalDefId — the body being checkedtypeck_results: RefCell<TypeckResults<'tcx>> — accumulated resultsTypeckRootCtxt holds deferred checks that need to wait until inference has progressed: deferred_cast_checks, deferred_asm_checks, deferred_repeat_expr_checks, deferred_transmute_checks.
Sources: compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs1-100 compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs1-50
The main dispatch is in check_expr_kind (compiler/rustc_hir_typeck/src/expr.rs343-423) which matches on ExprKind and calls a specialized checker for each variant:
| ExprKind | Handler |
|---|---|
Lit | check_expr_lit |
Binary | check_expr_binop |
MethodCall | check_expr_method_call |
Call | check_expr_call |
Closure | check_expr_closure |
Match | check_expr_match |
Block | check_expr_block |
Struct | check_expr_struct |
Field | check_expr_field |
Index | check_expr_index |
Cast | check_expr_cast |
Yield | check_expr_yield |
The main entry check_expr_with_expectation (compiler/rustc_hir_typeck/src/expr.rs226-340) handles divergence tracking, unreachable code warnings, and calls write_ty to record the result.
Expectation is an enum that guides inference:
NoExpectation — no hintExpectHasType(Ty) — require subtype relationshipExpectCastableToType(Ty) — weaker, for cast targetsExpectRvalueLikeUnsized(Ty) — for unsized valuesSources: compiler/rustc_hir_typeck/src/expr.rs57-423 compiler/rustc_hir_typeck/src/expectation.rs1-50
Pattern checking is in pat.rs via check_pat_top → check_pat → check_pat_inner (compiler/rustc_hir_typeck/src/pat.rs380-478).
Key concepts:
AdjustMode — controls whether references are peeled from the scrutinee before matching (Peel vs Pass)PeelKind — Implicit (standard match ergonomics) or ExplicitDerefPat (for deref!(_) patterns)MutblCap — tracks whether ref mut bindings are permitted under current context (RFC 3627 Rule 3)InheritedRefMatchRule — controls how & patterns interact with inherited references (RFC 3627 Rule 4), varies by editionPatInfo carries binding_mode, max_ref_mutbl, max_pinnedness, and current_depth through recursive pattern checking.
Sources: compiler/rustc_hir_typeck/src/pat.rs164-398
FnCtxt wraps an InferCtxt to create and unify type variables. Key methods:
next_ty_var / next_region_var / next_const_var — create fresh inference variablesresolve_vars_if_possible — substitute resolved variablesresolve_vars_with_obligations — additionally runs trait selection to resolve more variablesselect_obligations_where_possible — drives the obligation machineryThe Coerce struct (compiler/rustc_hir_typeck/src/coercion.rs72-88) implements all coercion logic. It walks through a sequence of coercion rules:
! coerces to any type&mut T → &T, *mut T → *const T, unsized coercionsDeref implsT → &T or &mut T[T; N] → [T], Concrete → dyn TraitCoerceMany (compiler/rustc_hir_typeck/src/coercion.rs1-100) is used when multiple branches (e.g., match arms, if/else) must be unified into a single type using the LUB (least upper bound) operation.
The key external entry points on FnCtxt are:
demand_coerce / demand_coerce_diag — enforce a coercion, emitting an error if impossibledemand_suptype — require actual <: expecteddemand_eqtype — require strict type equalitySources: compiler/rustc_hir_typeck/src/coercion.rs72-137 compiler/rustc_hir_typeck/src/demand.rs1-70
Method resolution is the most complex part of rustc_hir_typeck. It is split into two phases: probe (find candidates) and confirm (apply the selected candidate).
Method Resolution Pipeline
Sources: compiler/rustc_hir_typeck/src/method/probe.rs1-100 compiler/rustc_hir_typeck/src/method/confirm.rs1-50 compiler/rustc_hir_typeck/src/method/suggest.rs191-420 compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs213-231
ProbeContext and Candidate AssemblyProbeContext (compiler/rustc_hir_typeck/src/method/probe.rs51-88) is constructed with the receiver type and method name. Candidate assembly walks an autoderef chain — the sequence of types obtained by repeatedly dereferencing — and for each type collects:
tcx.inherent_impls(adt_did)The autoderef steps are computed via a canonical query method_autoderef_steps (from rustc_trait_selection) to enable caching.
CandidateKind variants:
| Variant | Meaning |
|---|---|
InherentImplCandidate | Method from an inherent impl |
ExtensionImplCandidate | Method from a trait impl |
ObjectCandidate | Method from a dyn Trait vtable |
TraitCandidate | Trait bound on a type parameter |
WhereClauseCandidate | Where-clause in the caller's environment |
Candidate filtering uses fast_reject for quick type-based elimination before running full trait selection.
Sources: compiler/rustc_hir_typeck/src/method/probe.rs51-170
method/confirm.rs)Once a Pick is chosen, confirm_method instantiates the method's generic arguments, applies auto-deref and auto-borrow adjustments to the receiver, and registers obligations for trait bounds. The result is a MethodCallee containing:
def_id: DefId — the resolved methodargs: GenericArgsRef<'tcx> — substituted generic argumentssig: FnSig<'tcx> — instantiated function signaturereport_method_error (compiler/rustc_hir_typeck/src/method/suggest.rs191-420) handles MethodError variants:
MethodError variant | Meaning |
|---|---|
NoMatch(NoMatchData) | No applicable method found |
Ambiguity(Vec<CandidateSource>) | Multiple equally applicable methods (E0034) |
PrivateMatch(DefKind, DefId, ...) | Method exists but is private (E0624) |
IllegalSizedBound | Method requires Sized on a trait object |
BadReturnType | Wrong return type in probe |
For NoMatch, the suggestion machinery tries many recovery paths:
.into_iter() for IntoIterator types calling Iterator methodssuggest_valid_traits)suggest_associated_call_syntax)suggest_use_shadowed_binding_with_method)Closure typing (compiler/rustc_hir_typeck/src/closure.rs) determines the FnOnce/FnMut/Fn kind of a closure and infers its signature. The process:
Fn trait (based on captures).CoroutineTypes if the closure is async.Deferred call resolutions (DeferredCallResolution) handle the case where a closure's FnX kind is not yet known at the call site — they are resolved later when the closure type is finalized.
Sources: compiler/rustc_hir_typeck/src/closure.rs1-60 compiler/rustc_hir_typeck/src/callee.rs1-50
After type inference is complete, writeback.rs substitutes all inference variables with their resolved types and writes the final results into TypeckResults.
Writeback resolves:
node_types — the type of every HIR nodenode_args — generic arguments at each use sitetype_dependent_defs — resolved method/associated item at each calladjustments — auto-deref/auto-borrow sequencespat_adjustments — implicit deref steps in patternsliberated_fn_sigs — closure/function signatures with late-bound regions freedupvar_capture_map — how each upvar is capturedAny inference variable that was not fully resolved by this point causes an "type annotations needed" error.
Sources: compiler/rustc_hir_typeck/src/writeback.rs1-50
Code Entity Data Flow
Sources: compiler/rustc_hir_typeck/src/writeback.rs1-60 compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs1-100 compiler/rustc_hir_analysis/src/collect.rs60-97 compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs122-210
| Type / Trait | File | Role |
|---|---|---|
ItemCtxt | rustc_hir_analysis/src/collect.rs:128 | HIR lowering context for items; no inference |
HirTyLowerer | rustc_hir_analysis/src/hir_ty_lowering/mod.rs:126 | Trait for converting hir::Ty → ty::Ty |
WfCheckingCtxt | rustc_hir_analysis/src/check/wfcheck.rs:48 | Context for WF obligation registration |
FnCtxt | rustc_hir_typeck/src/fn_ctxt/mod.rs | Body-checking context with InferCtxt |
TypeckRootCtxt | rustc_hir_typeck/src/typeck_root_ctxt.rs | Shared deferred checks for a body owner |
ProbeContext | rustc_hir_typeck/src/method/probe.rs:51 | Method candidate search context |
Coerce | rustc_hir_typeck/src/coercion.rs:72 | Coercion rule application |
CoerceMany | rustc_hir_typeck/src/coercion.rs | LUB coercion across multiple sites |
TypeckResults | rustc_middle | Final per-body type information map |
MethodCallee | rustc_hir_typeck/src/method/mod.rs | Resolved method: def_id, args, sig |
MethodError | rustc_hir_typeck/src/method/mod.rs | Method lookup failure variant |
NoMatchData | rustc_hir_typeck/src/method/mod.rs | Data for MethodError::NoMatch suggestions |
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.