Skip to content

A switch's default clause falls through like any other clause - #538

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-switch-default-fallthrough
Oct 11, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-switch-default-fallthrough

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Problem

A default clause without a break never fell through into the clauses after it. It jumped straight out of the switch:

function t(x: number) {
    let r = "";
    switch (x) {
        default: r += "q";   // fallthrough
        case 6:  r += "x";   // fallthrough
        case 8:  r += "y"; break;
    }
    return r;
}
t(100)   // "q", expected "qxy"

The same happened with default in the middle. docs/bugs/testFallThrough.ts reports fail: q !== qxy.

Cause

mlirGenSwitchCase ends each clause body with a branch to the merge block. If the body has no break, that branch is put in pendingBranches so that the next clause points it at its own body. The condition was !hasBreak && !isDefaultCase, so a default body always branched to the end of the switch.

Fix

Drop !isDefaultCase. When default is the last clause, its pending branch is never re-pointed and keeps the merge block it was created with, the same as for a last case.

Testing

  • New 00switch_default_fallthrough.ts (compile + JIT + rc/none corpus): default first, in the middle, and last, plus default with break. The current release fails with assertion failed: defaultFirst(100).
  • docs/bugs/testFallThrough.ts now prints all OK.
  • Full ctest: 3919/3919 pass.

🤖 Generated with Claude Code

Without a `break`, a `default` body jumped straight out of the switch
instead of into the clause after it: `default: r += "q"; case 6: r += "x"`
gave "q", not "qx". mlirGenSwitchCase left the body's exit pending (to be
pointed at the next clause's body) for every clause except `default`.

Found by docs/bugs/testFallThrough.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 9b9974a into main Oct 11, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-switch-default-fallthrough branch October 11, 2026 12:32
ASDAlexander77 added a commit that referenced this pull request Oct 12, 2026
…558)

Every repro in docs/bugs passes on main, or fails as TypeScript does:
the native_ts_graphics findings were fixed by #535-#544 and #549 (the
`let s = 0` one by design, with a warning since #544), testFallThrough,
generic_in_generic and array_of_ifaces_cast by #538, #542 and #543, and
bug14 and bug21 aren't valid TypeScript. Each fix has its regression
test in tslang/test/tester, and the findings document is in the history
and in those PRs, so the folder goes.

Its interop notes stay, in docs/c-cpp-header-import.md: a `string`
returned by a C function is its `char*`, not a copy; `number` is a
`double`; and a nullable `Ref<T>` field is spelled `Ref<T> | null`.

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