fix(types): register failed-assignment targets during checker error recovery - #610
Conversation
…ecovery When an assignment's RHS fails to type-check, the checker never registered the assignment target in the type environment, so every later use of that variable produced a misleading follow-on `Undefined variable: $x` — burying the one real diagnostic under noise for a variable the program clearly defines. Recover by poisoning the target as `Mixed` (unknown) when its initializer fails, for both `$x = ...` and typed `T $x = ...` forms (inference failure and declared-type mismatch). `Mixed` is treated as "unknown, do not diagnose", so downstream uses (`count($x)`, indexing, reassignment) are accepted silently and one bad assignment no longer cascades into one error per later use. Genuinely undefined variables are still reported. Poisoned top-level targets are recorded so the method-body pass can drop them from the environment it inherits from top level: a poisoned `Mixed` merged with a same-named method local would otherwise stay `Mixed` and spawn a spurious return-type error. Claude-Session: https://claude.ai/code/session_01HRvbcjPHa3kAojdCjNZL5L
|
Two adjacent pre-existing findings, both reverified on current main + this branch, filed separately: #611 (method bodies seed their env from top-level locals — a genuine mixed top-level local still poisons a same-named method local on error-free programs; this PR only shields the recovery-poisoned case) and #612 (the same failed-RHS cascade in the remaining binding forms — list unpack and reference assignment — which can reuse this PR's recovery machinery). |
|
Updated this PR in place on top of current What changed:
This also closes the two residual gaps called out above and tracked in #611 and #612. Local validation:
Published head: |
…n-recovery # Conflicts: # CHANGELOG.md
Summary
When the right-hand side of an assignment fails to type-check, the checker never
registered the assignment target in the type environment. Every later use of that
variable then produced a misleading follow-on
Undefined variable: $x— burying theone real diagnostic under noise for a variable the program clearly defines. On larger
programs a single bad expression cascaded into a wall of
Undefined variableerrors.Fixes #597.
Reproduction
Before:
error: Spread operator requires an array(correct) pluserror: Undefined variable: $s(noise). After: only the spread error.Root cause
In
check_assign/check_typed_assign(src/types/checker/stmt_check/assignments/locals.rs)the RHS inference error was propagated with
?before the target was inserted into thetype environment, so the symbol never existed for later statements. The per-statement
checker driver continues after an error, so each later read of the target raised a
follow-on
Undefined variable.Fix
Error recovery now poisons the failed target as
Mixed(only when unbound, preserving avalid earlier binding) before propagating the real RHS error, for both
$x = ...and typedT $x = ...forms (inference failure and declared-type mismatch).Mixedis treated as"unknown, do not diagnose", so downstream uses (
count($x), indexing, reassignment) areaccepted silently and one bad assignment no longer cascades into one error per use.
Genuinely undefined variables are still reported.
Method bodies seed their base environment from the top-level environment, so a poisoned
top-level target is recorded and dropped from that seed; otherwise, merged with a same-named
method local it would stay
Mixedand spawn a spurious return-type error. This is scoped toalready-failing programs (a poison only occurs on an assignment error), so compiling programs
are unaffected — with no poisoned targets the method seed is identical to before.
Tests
Six regression tests in
tests/error_tests/recovery.rs: the exact repro emits only thespread error; many later uses still emit exactly one error; a genuinely undefined variable is
still reported; a typed-assignment failure does not cascade; a valid spread assignment still
type-checks; and a poisoned top-level target does not leak into a same-named method local.
Full
error_testssuite green (1114 passed, 0 failed), including the image-builtin test thatcaught the method-seed interaction during development. Focused codegen slice
class method assigngreen (1241 passed).cargo buildclean.https://claude.ai/code/session_01HRvbcjPHa3kAojdCjNZL5L