Open-Source Wikis

/

Rust

/

Compiler

/

HIR analysis and type checking

rust-lang/rust

HIR analysis and type checking

After lowering, rustc has a fully name-resolved HIR but still needs to assign types to expressions, check trait obligations, run lints, and verify well-formedness. Two crates do most of the heavy lifting.

rustc_hir_analysis — item-level checks

compiler/rustc_hir_analysis/ handles checks that operate at the item level:

  • Collection — figuring out the type of every item (type_of, fn_sig, predicates_of queries) from its HIR
  • Well-formedness — every type/clause is well-formed (e.g., bounds on generics are coherent, associated types are bounded)
  • Coherence — no two impl blocks overlap (the orphan rule and friends). This is the core of trait soundness.
  • Variance — phantom variance computation for ADTs
  • Outlives requirements — implicit T: 'a bounds derived from struct fields
  • Astconv — converting HIR types (which are syntactic) into Ty<'tcx> (which are semantic)

These all run before per-function type checking and produce the queries that feed it.

rustc_hir_typeck — function-body type checking

compiler/rustc_hir_typeck/ is the per-function type checker. For every function body it:

  1. Sets up an InferCtxt with fresh inference variables for each unspecified type
  2. Walks the HIR top-down, generating type and trait constraints
  3. Solves trait obligations against the constraint set
  4. Resolves inference variables to concrete types
  5. Reports type errors, suggesting fixes via diagnostics

It produces a TypeckResults<'tcx> keyed by HirId, recording the inferred type of every expression, the resolution of every method call, the type of every pattern binding, and the trait obligations satisfied along the way.

Pipeline

graph TB
    HIR[(HIR after lowering)]
    HIR --> Collect[Collection<br/>type_of, fn_sig,<br/>predicates_of, …]
    Collect --> WF[Well-formedness checks]
    WF --> Coherence[Coherence checks]
    Coherence --> Typeck[rustc_hir_typeck<br/>per-fn typing]
    Typeck --> Output[(TypeckResults<br/>per body)]
    Output --> NextStage[MIR build]

The collection / well-formedness / coherence steps are queries — they're computed lazily when other parts of the compiler ask. rustc_hir_typeck::typecheck_item_bodies is the entry point that demands them all at once.

Inference walkthrough

Take fn add(a: i32, b: i32) -> i32 { a + b }. Type checking proceeds:

  1. Function signaturefn_sig query returns fn(i32, i32) -> i32. a and b are bound as i32.
  2. Body type — fresh inference variable ?T introduced for the body.
  3. Expression a + b — looks up <i32 as Add<i32>>::add. The Add trait is satisfied. Result type is i32.
  4. Tail constraint?T = i32 (because the body's last expression must equal the return type).
  5. Resolution?T resolves to i32. No errors.

For complex examples involving closures, async, and trait inference, the work is much heavier — but the structure is the same.

Method resolution

Method calls (x.foo()) are resolved by rustc_hir_typeck::method, which:

  1. Builds a list of candidate methods (inherent impls, then trait impls in scope) considering autoderef and autoref
  2. Picks the most specific candidate
  3. Generates the obligations needed to satisfy the chosen impl's where-clauses

Method resolution is a frequent source of subtle bugs because it interacts with autoderef, autoref, dyn dispatch, and inference simultaneously.

Coercions

Implicit conversions (&T&dyn Trait, &[T; N]&[T], Box<T>Box<dyn Trait>) are handled by rustc_hir_typeck::coercion. Coercions are numbered and sequenced; complex coercion paths can produce CoerceMany records.

Diagnostics

Type errors are some of rustc's most user-visible output. The frontend goes to extra effort to produce them well:

  • Suggestion machinerytcx.dcx().struct_span_err(...).help_with_suggestion(...) produces actionable hints
  • Trait engine fallbacks — when a trait obligation fails, the trait engine produces a list of why
  • note: expected … found … — formatting unifies the printer with the type-error formatter

Patterns to look for in diagnostics code: try_report_*, suggest_*, note_* methods on the relevant context.

Lints in the analysis phase

Some lints run during HIR analysis (for items, attributes, dead code, unused imports). Others run later, on MIR (unused_assignments, dead-store removal). The framework is in rustc_lint and lint definitions in rustc_lint_defs.

Pattern exhaustiveness

Pattern matching exhaustiveness (match x { … } covers every case) is checked separately by rustc_pattern_analysis. The crate is shared with rust-analyzer (it's published to crates.io as well). The algorithm is based on Maranget's "Compiling Pattern Matching to Good Decision Trees" and is one of the cleaner stand-alone pieces of the type-checker.

Privacy

rustc_privacy checks visibility on item references after type checking. It enforces:

  • You can only reference items you can name (pub(crate), pub(super), …)
  • You can't expose more in your public API than you have visibility for ("private-in-public" lint)

Key files

File What
compiler/rustc_hir_analysis/src/lib.rs Top-level entry, registers queries
compiler/rustc_hir_analysis/src/collect.rs "Collect" pass — types/preds/sigs from HIR
compiler/rustc_hir_analysis/src/coherence/ Coherence/orphan checks
compiler/rustc_hir_typeck/src/lib.rs Per-function entry
compiler/rustc_hir_typeck/src/fn_ctxt/ The FnCtxt that holds typeck state
compiler/rustc_hir_typeck/src/method/ Method resolution
compiler/rustc_hir_typeck/src/expr_use_visitor.rs Closure capture analysis

Entry points for modification

  • A new diagnostic suggestion in typeck → find the relevant report_* or suggest_* method
  • New rule for method dispatch → rustc_hir_typeck::method
  • Item-level well-formedness change → rustc_hir_analysis::check::wfcheck
  • New lint that wants HIR access → register a LateLintPass in rustc_lint::late
  • Pattern-exhaustiveness rule → rustc_pattern_analysis

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

HIR analysis and type checking – Rust wiki | Factory