Skip to content

An error in code the compiler makes is reported at the code it was made for - #581

Merged
ASDAlexander77 merged 2 commits into
mainfrom
synthesized-node-location
Oct 17, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
synthesized-node-location

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Nodes the compiler builds with NodeFactory have no position, so an error inside one was reported at 1:1 of the file:

function main() {
    const n = 5;
    for (const x of n) {}   // was 1:1, now 3:5: Can't resolve property 'length' of type s32
    using r = 5;            // was 1:1, now 4:11: Can't resolve property 'dispose' of type s32
}

Found for for...of, for...in, for await, yield*, a class [Symbol.iterator], using and await using. #541 and #557 fixed the generated cast, field initializers and the implicit constructor one site at a time (stamping pos). This fixes the rest in one place:

  • mlirGen(Statement) records where the statement is, as a location without the debug scope (generatedNodesAnchor). A statement the compiler made itself (no position) keeps the anchor of the one it was made for.
  • loc() gives a node with no position (isTextRangeEmpty()) that anchor, fused with the current overwriteLoc and debug scope. Nodes with a position are unchanged.
  • The dispose call is built at the scope's exit; mlirGenDisposeOne anchors it at the using declaration.

The anchor holds no debug scope, so a node is never given a scope from another function: --di JIT and --di --emit=obj of loops, using and yield* were checked.

Tests: diagnostic-location/for_of.ts, for_in.ts, using.ts, error text with line and column, failing on any :1: position. The existing three diagnostic-location tests still pass.

Full Release suite: 4092/4092 passed.

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits October 17, 2026 12:32
…de for

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>
…nto synthesized-node-location

# Conflicts:
#	tslang/test/tester/CMakeLists.txt
@ASDAlexander77
ASDAlexander77 merged commit 3d23593 into main Oct 17, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the synthesized-node-location branch October 17, 2026 13:06
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