From 4299facb1ece18fd9344119574d0566c8702eb18 Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Sun, 11 Oct 2026 13:20:19 +0100 Subject: [PATCH] Errors in a generated cast are reported where the cast is 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 --- tslang/lib/TypeScript/MLIRGenCast.cpp | 33 ++++++++++--------- tslang/test/tester/CMakeLists.txt | 11 +++++++ .../diagnostic-location/generated_cast.ts | 10 ++++++ 3 files changed, 38 insertions(+), 16 deletions(-) create mode 100644 tslang/test/tester/diagnostic-location/generated_cast.ts diff --git a/tslang/lib/TypeScript/MLIRGenCast.cpp b/tslang/lib/TypeScript/MLIRGenCast.cpp index 79fb3380f..cfe19922b 100644 --- a/tslang/lib/TypeScript/MLIRGenCast.cpp +++ b/tslang/lib/TypeScript/MLIRGenCast.cpp @@ -2116,15 +2116,17 @@ namespace mlirgen auto src = ss.str(); - { - MLIRLocationGuard vgLoc(overwriteLoc); - overwriteLoc = location; + // The generated function's body is generated when the call below instantiates it, not when + // it is parsed, so the call site has to stay the location until then. Without it a + // diagnostic there took the generated text's offset as a position in the user's file - an + // error reported inside a comment on line 1. + MLIRLocationGuard vgLoc(overwriteLoc); + overwriteLoc = location; - if (mlir::failed(parsePartialStatements(src))) - { - assert(false); - return mlir::failure(); - } + if (mlir::failed(parsePartialStatements(src))) + { + assert(false); + return mlir::failure(); } auto funcResult = resolveIdentifier(location, funcName, genContext); @@ -2308,15 +2310,14 @@ namespace mlirgen auto src = ss.str(); - { - MLIRLocationGuard vgLoc(overwriteLoc); - overwriteLoc = location; + // kept until the call below has instantiated the function - see castPrimitiveTypeFromAny + MLIRLocationGuard vgLoc(overwriteLoc); + overwriteLoc = location; - if (mlir::failed(parsePartialStatements(src))) - { - assert(false); - return mlir::failure(); - } + if (mlir::failed(parsePartialStatements(src))) + { + assert(false); + return mlir::failure(); } auto funcResult = resolveIdentifier(location, funcName, genContext); diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index 7a9a4d06e..bf19ce3b6 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -2613,6 +2613,17 @@ foreach(call_arity_case ${call_arity_cases}) FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed") endforeach() +# An error inside a cast function the compiler generates (here: null in a union cast to string) is +# reported where the cast is - line 6 - and not at the generated text's offset taken as a position +# in the user's file, which put it inside the comment on line 1. +add_test(NAME test-compile-diagnostic-location-generated-cast + COMMAND $ --emit=obj --no-default-lib -mm=none + "${PROJECT_SOURCE_DIR}/test/tester/diagnostic-location/generated_cast.ts" + -o "${CMAKE_CURRENT_BINARY_DIR}/diagnostic-location-generated-cast.obj") +set_tests_properties(test-compile-diagnostic-location-generated-cast + PROPERTIES PASS_REGULAR_EXPRESSION "generated_cast\\.ts:6:23: error: can't cast from 'null' to 'string'" + FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed|generated_cast\\.ts:1:") + # A call to the collector's API (GC_gcollect, or the weak-link functions DefaultLib's WeakRef uses) # is an error under every model but gc, which alone links the collector - it used to reach the # linker as an unresolved symbol. Under gc the same file compiles. diff --git a/tslang/test/tester/diagnostic-location/generated_cast.ts b/tslang/test/tester/diagnostic-location/generated_cast.ts new file mode 100644 index 000000000..4f396f44b --- /dev/null +++ b/tslang/test/tester/diagnostic-location/generated_cast.ts @@ -0,0 +1,10 @@ +// An error inside the cast function the compiler generates for a union was reported at the +// generated text's offset taken as a position in this file - inside this comment - rather than +// where the cast is. + +function text(x: number | string | null): string { + const s: string = x; + return s; +} + +print(text("a"));