Skip to content

Leave no half-built ts.If behind when a conditionalValue branch fails - #352

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-conditional-value-failure
Sep 23, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-conditional-value-failure

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Summary

When a branch failed, MLIRCodeLogicHelper::conditionalValue returned failure but left its IfOp in the IR, with an empty or none-typed region, and left the insertion point inside it. If the caller carried on, the failure turned into bad IR further on. For example, x instanceof C of a -shared class, before #351, gave "'ts.If' op expects a non-empty block" instead of the branch's own error.

It now erases the IfOp and puts the insertion point back before returning failure.

Verification

#351 removed the trigger, so no ordinary program reaches this failure path any more, and there's no new regression test. I checked it by temporarily forcing mlirGenInstanceOfOpaque to fail for a dynamically imported class: print(a instanceof M.Failure) now stops with that forced error rather than the verifier error.

Found but not fixed here

The same forced failure inside the generated ___unbox<C> (the <C>anyValue cast) is still swallowed. The instantiation compiles without the failed if (a instanceof C) return a;, so the cast always throws "Can't cast from any type", and no error is printed. The error is raised in the real pass (not dummy, not partial resolve). The most likely explanation is that a failed generic instantiation leaves its function in the module and a retry reuses it. That's the "dirt" TODO in mlirGenNoScopeVarsAndDisposable: a general MLIRGen issue, outside this PR.

Tests

  • Windows Release: 2843/2843 passed.
  • Linux (WSL): 2837/2837 passed.

🤖 Generated with Claude Code

MLIRCodeLogicHelper::conditionalValue returned failure with its IfOp still in
the IR - an empty or none-typed region - and the insertion point still inside
it. Whenever the caller carried on, the failure turned into bad IR further on:
"'ts.If' op expects a non-empty block" in place of the branch's own error
(seen as `x instanceof C` of a -shared class before #351). It now erases the
IfOp and puts the insertion point back before returning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 5d281cb into main Sep 23, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-conditional-value-failure branch September 23, 2026 16:56
ASDAlexander77 added a commit that referenced this pull request Sep 24, 2026
`f?.(1)` for a callee that needs two arguments failed with TS2554 but
left its ts.If in the IR, with a then-block holding no ResultOp and an
unfilled else. #352 fixed the same shape in conditionalValue. The if is
now erased before the failure is returned.

No caller carries on after this failure today: at every site tried
(local, module level, class field, template literal, ??, typeof) the
compile stops with the TS2554 error alone, on main as well. This keeps
it that way for a caller that does. The new call-arity case,
optional_call_value, uses the result inside an expression at module
level, in a global's initializer.

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