Origin: Surfaced during PR #631's review pass while writing a source-location assertion for the new [E615] diagnostic test.
The pattern
When _translate_interpolated_string records a failing segment in WasmContext._interp_inference_failures and the harvest in CodeGenerator._compile_fn emits an [E615] diagnostic, the diagnostic's source location reads from the failing AST node's .span. For SlotRef nodes inside an interpolation segment (e.g. "\(@Option<Int>.0)"), the span is unreliable — the diagnostic line/column lands on adjacent syntax (e.g. the closing brace of an earlier construct, line 3 in the test fixture rather than the actual line 9 of the SlotRef).
This is a transformer / parser concern, not a codegen one — the AST node is being constructed with the wrong span by vera/transform.py or the upstream Lark tree.
Why it matters
PR #630's Tier 2 framing is: "convert silent miscompilation into source-located diagnostic". The diagnostic is loud — visible as [E615] — but its source location can be wrong, which undercuts the "source-located" half of the contract. The TestE615LoudInterpolationFallthrough630::test_e615_fires_on_adt_in_interpolation test was softened during PR #631 review (assertion changed from "line ≥ 5" to "line > 0") to accommodate this; once fixed, the assertion can be tightened to actually verify the line points at the segment.
Recommended fix
Audit how SlotRef nodes are constructed inside InterpolatedString.parts. Likely candidates:
- The Lark grammar for interpolation segments may not propagate per-segment positions correctly.
vera/transform.py may be using the parent InterpolatedString's span when constructing inner SlotRefs.
A reproducer test fixture exists in tests/test_codegen.py::TestE615LoudInterpolationFallthrough630::test_e615_fires_on_adt_in_interpolation (the softened assertion). Tightening that assertion is the natural acceptance test.
Out of scope for #630
#630's scope was the canonicalisation walker + the loud-skip mechanism, not span fidelity. Span issues affect every diagnostic that points at AST nodes constructed in this way, not just [E615].
Pairs with
Origin: Surfaced during PR #631's review pass while writing a source-location assertion for the new
[E615]diagnostic test.The pattern
When
_translate_interpolated_stringrecords a failing segment inWasmContext._interp_inference_failuresand the harvest inCodeGenerator._compile_fnemits an[E615]diagnostic, the diagnostic's source location reads from the failing AST node's.span. ForSlotRefnodes inside an interpolation segment (e.g."\(@Option<Int>.0)"), the span is unreliable — the diagnostic line/column lands on adjacent syntax (e.g. the closing brace of an earlier construct, line 3 in the test fixture rather than the actual line 9 of the SlotRef).This is a transformer / parser concern, not a codegen one — the AST node is being constructed with the wrong span by
vera/transform.pyor the upstream Lark tree.Why it matters
PR #630's Tier 2 framing is: "convert silent miscompilation into source-located diagnostic". The diagnostic is loud — visible as
[E615]— but its source location can be wrong, which undercuts the "source-located" half of the contract. TheTestE615LoudInterpolationFallthrough630::test_e615_fires_on_adt_in_interpolationtest was softened during PR #631 review (assertion changed from "line ≥ 5" to "line > 0") to accommodate this; once fixed, the assertion can be tightened to actually verify the line points at the segment.Recommended fix
Audit how
SlotRefnodes are constructed insideInterpolatedString.parts. Likely candidates:vera/transform.pymay be using the parent InterpolatedString's span when constructing inner SlotRefs.A reproducer test fixture exists in
tests/test_codegen.py::TestE615LoudInterpolationFallthrough630::test_e615_fires_on_adt_in_interpolation(the softened assertion). Tightening that assertion is the natural acceptance test.Out of scope for #630
#630's scope was the canonicalisation walker + the loud-skip mechanism, not span fidelity. Span issues affect every diagnostic that points at AST nodes constructed in this way, not just
[E615].Pairs with