Skip to content

semantic: reject bare case-declarations without a block #601

@cs01

Description

@cs01

Motivation

#597 turned out to be caused by `parser-native`'s switch_case iteration silently dropping the trailing `return` when a bare case body contained a `[lexical_declaration, if, return]` sequence. Wrapping the case in `{}` fixes it. Other bare multi-statement case bodies may be lurking undetected in the compiler source.

The TypeScript community solved this exact class with the `no-case-declarations` ESLint rule. We should enforce it at the semantic-pass layer so future bugs in this category are compile errors, not silent-wrong native output.

Proposal

New semantic pass in `src/semantic/case-declarations-checker.ts`:

  1. Walk every `SwitchStatement` in the AST (or every desugared if-ladder that came from a switch).
  2. For each case's `consequent`, if any statement is a `variable_declaration` / `lexical_declaration` AND the consequent is not a single `BlockStatement` wrapping all of it: emit a compile error pointing at the declaration.
  3. Fix suggestion in the error: "wrap the case body in braces: `case X: { ... }`".

Wire into `LLVMGenerator.generateParts()` alongside `checkClosureMutations`, `checkUnionTypes`, etc.

Why this is the right fix

Root cause of #597 is deeper in parser-native's tree-sitter handling of bare case bodies — real fix is there, but until that lands, a compile-time rejection is a cheap guard against silent-wrong output. TypeScript itself rejects this pattern in strict mode (`no-case-declarations`), so the constraint is already familiar to users.

Scope

Related: #597 (the bug this prevents future variants of).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions