Skip to content

Map TypeCheckErrorKind to official errorCodes #81

Closed

Description

@biuld

Part of #74 (Phase 1). The cheapest item in the plan: TypeCheckErrorKind already distinguishes every case needed, but error_code() returns None for all but two, so 153 corpus cases are unmeasurable.

Do now — no semantic risk

Kind Code Corpus cases
TypeMismatch TypesDoNotUnify 41
OccursCheck InfiniteType 2
IntegerOutOfRange IntOutOfRange 1
NoInstance NoInstanceFound 53
OverlappingInstances OverlappingInstances 8
MissingInstanceMethod MissingClassMember 2

EscapedSkolem and InvalidCoercibleInstanceDeclaration are already mapped.

Need a purs semantics decision first

  • UnconstrainedType (emitted at crates/psrs-typecheck/src/typecheck/unify.rs:314 and rows.rs:217 for "cannot infer a monomorphic type") — compare against purs' WildcardInferredType (a warning) and CannotApplyExpressionOfTypeOnType. Do not guess; read purs and pick.
  • AmbiguousConstraint (classes/fundeps.rs:293) — compare against AmbiguousTypeVariables and UnconstrainedTypeVariable.
  • FundepConflict — compare against FunctionalDependencyError / the fundep diagnostics in the corpus.

Note

crates/psrs-driver/src/tests/coercion.rs:7 currently accepts a NoInstanceFound assertion by falling back to a message-text match, precisely because the code is absent. Tighten that helper once the code exists; a message-text fallback in a test is a hidden gap.

Acceptance

error_code() covers every kind that has an unambiguous official code, coercion.rs matches on codes only, and the L4/L5 scoreboards report a non-zero baseline for TypesDoNotUnify and NoInstanceFound.

References

  • crates/psrs-typecheck/src/typecheck/error.rs
  • docs/design/D-04-suite-roadmap.md — M4, M5 suite lists

Activity

  1. added
    gate:L4Blocks core type checking (D-04 L4)
    gate:L5Blocks type classes and instances (D-04 L5)
    area:harnessScoreboard, corpus, or measurement infrastructure
    on Oct 1, 2026
  2. biuld commented on Oct 2, 2026

    @biuld
    OwnerAuthor

    Landed in #110. The six mappings are in, and the three that needed a purs decision are decided from the source, not guessed.

    Mapped: TypeMismatch → TypesDoNotUnify, OccursCheck → InfiniteType, IntegerOutOfRange → IntOutOfRange, NoInstance → NoInstanceFound, MissingInstanceMethod → MissingClassMember, AmbiguousConstraint → AmbiguousTypeVariables.

    Decided against mapping, with the reading:

    • UnconstrainedType — I checked 0.15.16 on seven programs. purs has no error for an undetermined monomorphic variable: it generalizes the variable or reports the mismatch that left it unsolved. The issue's suggested WildcardInferredType is wrong twice over — it is a warning about a wildcard, not an error about a determined variable, and it fires while the variable is still solvable. Left unmapped; the honest code is whichever TypesDoNotUnify or UndefinedTypeVariable applies.
    • FundepConflict — there is no FunctionalDependencyError in Errors.hs at all. purs reports the consequence: RowInInstanceNotDetermined0/1 expect InvalidInstanceHead, raised in TypeChecker.checkTypeClassInstance for exactly this shape. A two-instance program confirms it — purs answers OverlappingInstances.
    • AmbiguousConstraint — mapped, with the stage difference recorded on the function. purs throws AmbiguousTypeVariables in TypeChecker/Types.hs with the same set of undetermined variables, but at generalization rather than while solving a goal.

    The hidden gap is closed: coercion.rs no longer falls back to a message-text match for NoInstanceFound. That test was passing for the wrong reason.

    The acceptance's baseline is met: L4 reports a non-zero TypesDoNotUnify (10/32) and L5 a non-zero NoInstanceFound (28/36). Full numbers in D-04 and #110.

    Note on issue ordering

    This was #81, but the L4/L5 scoreboards the acceptance refers to are #82's deliverable, so this change carries both: check_program_types_lenient and l4_l5_scoreboard_with_annotations land here alongside the mappings. Splitting them would have left one half unmeasurable — a mapping with no board reports nothing, and a board with no mappings measures a compiler that cannot emit codes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:harnessScoreboard, corpus, or measurement infrastructureenhancementNew feature or requestgate:L4Blocks core type checking (D-04 L4)gate:L5Blocks type classes and instances (D-04 L5)

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions