0%

Section 04: Type Resolution DRY

Status: Not Started Goal: The 6+ ParsedType resolution functions (resolve_parsed_type_simple, resolve_type_with_params, resolve_type_with_self/resolve_type_with_self_inner, resolve_and_check_type_with_vars, resolve_parsed_type, resolve_parsed_type_list) share an identical match-on-variant structure. Extract the shared tree walk into a generic resolver parameterized by how to handle type variables, Self, and unknown names. Context: This is the most severe algorithmic duplication in the type checker. All 5 functions walk the same ParsedType enum (Primitive, List, Map, Tuple, Function, Named, etc.) with identical recursive structure, differing only in: (a) how type parameters are resolved (fresh vars, lookup, error), (b) how Self is handled (fresh var, lookup, error), (c) whether to validate bounds. Additionally, dual string/Name well-known type tables create 2 more duplication sites.


04.1 Design TypeResolver Trait

File(s): compiler/ori_types/src/check/registration/type_resolution.rs, compiler/ori_types/src/check/signatures/mod.rs, compiler/ori_types/src/infer/expr/type_resolution.rs

Implementation note: The resolution functions operate on two different context types (ModuleChecker vs InferEngine). The shared trait must abstract pool_mut(), interner(), resolve_well_known_generic_cached(), and resolve_registration_primitive(). The InferEngine version handles additional variants (FixedList, Option, Result, Set, AssociatedType, ExistentialType, ConstGeneric) that the ModuleChecker ones do not.

  • Design a TypeResolveContext trait that abstracts:

    • pool_mut() -> &mut Pool — access to type pool (both ModuleChecker and InferEngine have this)
    • interner() -> &StringInterner — name interning
    • resolve_well_known_generic(name: Name, args: &[Idx]) -> Option<Idx> — well-known type lookup
    • resolve_registration_primitive(name: Name) -> Option<Idx> — primitive name resolution
  • Design a ResolveConfig struct that parameterizes:

    • resolve_type_param(name: Name) -> Idx — how to handle type parameters
    • resolve_self() -> Idx — how to handle Self type
    • resolve_unknown_name(name: Name) -> Idx — fresh var vs Idx::ERROR
    • check_bounds: bool — whether to validate trait bounds
  • Implement resolve_parsed_type_with<C: TypeResolveContext>() as the single canonical tree walk

  • Handle the variant coverage gap: the InferEngine version handles FixedList, Option, Result, Set, AssociatedType, ExistentialType, ConstGeneric — these MUST be supported in the canonical function (likely as optional handlers in the config)

  • Rewrite all 6+ existing functions as thin wrappers that construct the appropriate config and call the canonical function (including resolve_type_with_self, resolve_parsed_type_list)- [ ] Verify: the canonical function handles ALL ParsedType variants (Primitive, List, FixedList, Map, Tuple, Function, Named, Option, Result, Set, TraitBounds, SelfType, AssociatedType, ExistentialType, ConstGeneric, etc.)

  • Verify: all existing type checker tests pass unchanged

  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (04.1) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-04.1 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 04.1: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


04.2 Unify Well-Known Type Tables

File(s): compiler/ori_types/src/check/well_known/mod.rs

Two pairs of functions encode the same tables in both string and Name forms: resolve_well_known_generic() (string) / WellKnownNames::resolve_generic() (Name), and is_concrete_named_type() (string) / WellKnownNames::is_concrete() (Name).

  • WHERE: compiler/ori_types/src/check/well_known/mod.rs — find resolve_well_known_generic() (string-based) and corresponding WellKnownNames::resolve_generic() (Name-based); also find is_concrete_named_type() and WellKnownNames::is_concrete()

  • Make the string-based versions derive from the Name-based versions: string function interns the string, then delegates to the Name-based function. This ensures one canonical table.- [ ] If WellKnownNames is not always available (e.g., in isolated tests), provide a from_str() lookup that maps through interning rather than maintaining a parallel table

  • Verify: adding a new well-known type requires updating exactly ONE location — add a test that the string-based and Name-based tables produce identical results for all entries

  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (04.2) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-04.2 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 04.2: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


04.3 Add Unit/Never TypeDefs to Registry

File(s): compiler/ori_registry/src/defs/, compiler/ori_types/src/check/well_known/trait_set.rs, compiler/ori_types/src/infer/expr/registry_bridge/mod.rs

Unit and Never have no TypeDef in ori_registry, forcing hardcoded trait satisfaction fallbacks in ori_types at 3+ locations.

  • Add TypeDef for Unit in ori_registry with traits: Eq, Comparable, Hashable, Clone, Default, Debug, Printable

  • Add TypeDef for Never in ori_registry with appropriate traits

  • Remove hardcoded Unit trait satisfaction from trait_set.rs:229-236

  • Remove hardcoded Unit/Never fallbacks from registry_bridge/mod.rs:65-75

  • Verify: registry_satisfies_trait() correctly resolves Unit and Never traits via registry query

  • WARNING: Adding TypeDefs for Unit/Never changes how trait satisfaction is resolved for these types. Run timeout 150 cargo st to verify all spec tests pass — any test involving void or Never types could break if the trait set is wrong.

  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (04.3) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-04.3 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 04.3: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


04.R Third Party Review Findings

  • None.

04.T Test Strategy

This section refactors the most complex compiler subsystem (type resolution). Zero behavioral change, but high risk of subtle breakage.

  • Before any code changes: Snapshot the current timeout 150 cargo st output to detect any behavioral drift
  • Add unit tests for resolve_parsed_type_with() covering all ParsedType variants:
    • Primitive (int, float, str, bool, char, byte, void)
    • List, FixedList, Map, Tuple, Function
    • Named (user types, well-known generics)
    • Option, Result, Set
    • SelfType (with and without Self in scope)
    • AssociatedType, ExistentialType, ConstGeneric
    • TraitBounds
    • Each variant tested with each ResolveConfig mode (fresh vars, lookup, error)
  • Add enforcement test: well-known type string table and Name table produce identical results for all entries
  • Add enforcement test: Unit and Never trait satisfaction via registry matches the previous hardcoded behavior exactly
  • Verify timeout 150 cargo test -p ori_types passes after each sub-section (04.1, 04.2, 04.3)
  • Verify timeout 150 cargo st output is byte-identical to pre-change snapshot
  • Verify timeout 150 ./test-all.sh passes after all sub-sections complete

04.N Completion Checklist

  • Single canonical resolve_parsed_type_with() function
  • 6+ existing resolution functions are thin wrappers
  • Well-known type tables have single source (not dual string/Name)
  • Unit and Never have TypeDefs in ori_registry
  • No hardcoded trait satisfaction for Unit/Never in ori_types
  • Unit tests for canonical resolver cover all ParsedType variants x ResolveConfig modes
  • Enforcement tests for well-known tables and Unit/Never trait sets
  • timeout 150 cargo test -p ori_types passes
  • timeout 150 cargo test -p ori_registry passes
  • timeout 150 ./test-all.sh passes
  • ./clippy-all.sh clean
  • /tpr-review covering Section 04
  • /impl-hygiene-review
  • /improve-tooling retrospective completed — MANDATORY at section close, after both reviews are clean. Reflect on the section’s debugging journey (which diagnostics/ scripts you ran, which command sequences you repeated, where you added ad-hoc dbg!/tracing calls, where output was hard to interpret) and identify any tool/log/diagnostic improvement that would have made this section materially easier OR that would help the next section touching this area. Implement every accepted improvement NOW (zero deferral) and commit each via SEPARATE /commit-push. The retrospective is mandatory even when nothing felt painful — that is exactly when blind spots accumulate. See .claude/skills/improve-tooling/SKILL.md “Retrospective Mode” for the full protocol.