1ff7e811af
The four mut-local CheckError variants (MutAssignOutOfScope, AssignTypeMismatch, UnsupportedMutVarType, MutVarCapturedByLambda) embedded the bracketed kebab code in their thiserror Display body, while the non-JSON CLI formatter independently prepends [code] from CheckError::code() — doubling it. Non-mut variants never embedded the bracket; this brings the four in line with that convention. RED-first via the debug skill: ct1_check_cli.rs pins the observable property (code appears exactly once in the rendered human diagnostic). GREEN was a trivial four-string mechanical edit. Tests 598 -> 599.
60 lines
2.3 KiB
Markdown
60 lines
2.3 KiB
Markdown
# bugfix mut-diag-double-code — doubled `[code]` prefix in mut-local human diagnostics
|
|
|
|
**Date:** 2026-05-15
|
|
**Status:** DONE
|
|
**Trigger:** fieldtest finding F2 (`docs/specs/2026-05-15-fieldtest-mut-local.md`).
|
|
**Started from:** 1faee67
|
|
|
|
## Symptom
|
|
|
|
Non-JSON `ail check` stderr rendered the kebab diagnostic code
|
|
twice for the four mut-local `CheckError` variants, e.g.
|
|
|
|
```
|
|
error: [mut-var-captured-by-lambda] main: [mut-var-captured-by-lambda] mut-var `x` cannot be captured...
|
|
```
|
|
|
|
## Cause
|
|
|
|
`MutAssignOutOfScope`, `AssignTypeMismatch`,
|
|
`UnsupportedMutVarType`, `MutVarCapturedByLambda` were authored in
|
|
iters mut.2 / mut.4-tidy with their `#[error("[<code>] ...")]`
|
|
`thiserror` Display bodies embedding the bracketed code. The
|
|
non-JSON `Cmd::Check` formatter in `crates/ail/src/main.rs`
|
|
independently prepends `[{d.code}]` from `CheckError::code()`.
|
|
Embedded + prepended = doubled. The non-mut `CheckError` variants
|
|
never embedded the bracket, so only these four doubled — they were
|
|
the inconsistent ones, brought in line here.
|
|
|
|
## Fix
|
|
|
|
RED-first via the `debug` skill (`ailang-debugger` wrote the
|
|
failing test; the GREEN side was a trivial four-string mechanical
|
|
edit applied inline by the Boss per the CLAUDE.md
|
|
trivial-mechanical-edit carve-out — no review-and-commit
|
|
discipline shed).
|
|
|
|
- RED test: `crates/ail/tests/ct1_check_cli.rs` —
|
|
`check_human_mode_renders_mut_diagnostic_code_exactly_once`.
|
|
Pins the *observable* property: the code appears exactly once in
|
|
the rendered human diagnostic, exercising the same formatter path
|
|
the CLI uses (not a brittle assertion on the raw `#[error]` body).
|
|
- GREEN: dropped the leading `[<code>] ` literal from the four
|
|
`#[error(...)]` Display strings in `crates/ailang-check/src/lib.rs`.
|
|
|
|
The mut-typecheck pin tests (`mut_typecheck_pin.rs`) and the
|
|
in-source unit assertions match on the struct variants / `code()`,
|
|
not the Display string, so the prefix removal did not touch them.
|
|
|
|
## Tests
|
|
|
|
598 → 599 green (the new RED-now-GREEN human-formatter test).
|
|
Full workspace clean, zero failures.
|
|
|
|
## Not in scope (stays queued)
|
|
|
|
F1/F4 (accumulator-over-iteration: the milestone motivation is
|
|
unmet without a loop construct) and F3 (zero-arg `(app f)` rejected
|
|
at parse) from the same fieldtest are NOT addressed here — they are
|
|
design/roadmap items, not this bug.
|