Skip to content

Errors in a generated cast are reported where the cast is - #541

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-generated-cast-diagnostic-location
Oct 11, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-generated-cast-diagnostic-location

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Problem

An error inside a cast function the compiler generates was reported at a position that has nothing to do with the code:

// An error inside the cast function the compiler generates for a union was reported at the
// ...
function text(x: number | string | null): string {
    const s: string = x;          // the actual problem (null isn't a string)
generated_cast.ts:1:59: error: can't cast from 'null' to 'string' in 'strict null mode'
// An error inside the cast function the compiler generates for a union was reported at the

Issue 6 of docs/bugs/native-ts-graphics-findings.md shows the same thing: its first error points into the comment on line 1.

Cause

castFromUnion and castPrimitiveTypeFromAny build a generic __cast function from source text, parse it with overwriteLoc set to the call site, and then call it. The guard that set overwriteLoc was scoped to the parse only. The body is generated later, inside mlirGenCallExpression, when the call instantiates it. By then overwriteLoc was unknown again, so loc() mapped the generated text's offsets onto the user's source file.

Fix

Keep the guard alive until the call has instantiated the function, at both sites. With --di, parsePartialStatements already strips the debug metadata from overwriteLoc, and that stripped value is what stays in effect.

Testing

  • New test-compile-diagnostic-location-generated-cast (error-text test, like the call-arity ones): it requires generated_cast.ts:6:23: error: can't cast from 'null' to 'string' and fails on generated_cast.ts:1:. The current release prints 1:59.
  • A program that goes through both generated casts successfully (any to number, number | string to string) runs the same with no flags, --di, --di --opt, and as a --di exe.
  • Full ctest: 3914/3914 pass.

🤖 Generated with Claude Code

castFromUnion and castPrimitiveTypeFromAny generate a function from
source text and set the call site as the location while it is parsed.
But its body is generated later, when the call instantiates it, and by
then the location was reset: a diagnostic in the body took the generated
text's offset as a position in the user's file. `const s: string = x`
with `x: number | string | null` reported "can't cast from 'null' to
'string'" at 1:59, inside a comment. The call site now stays the
location until the call has instantiated the function.

Noticed while reviewing docs/bugs/native-ts-graphics-findings.md
(issue 6's first error pointed into a comment).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 4c5c032 into main Oct 11, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-generated-cast-diagnostic-location branch October 11, 2026 12:47
ASDAlexander77 added a commit that referenced this pull request Oct 17, 2026
…de for (#581)

A node the compiler builds (a for...of's or for...in's loop, the call of
`[Symbol.iterator]`, a `using`'s dispose call) has no position, so an
error in it was reported at 1:1:

    for (const x of 5) {}   // 1:1: Can't resolve property 'length' of type s32
    using x = 5;            // 1:1: Can't resolve property 'dispose' of type s32

Each statement now records where it is (without the debug scope), and
loc() gives a node with no position that location, in the current scope;
a statement the compiler made keeps the anchor of the one it was made
for. The dispose call, made at the scope's exit, is anchored at its
declaration. #541 and #557 had stamped positions on the generated cast
and constructor nodes one at a time; this covers the rest.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant