biome style/noUselessElse: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
function declarations inside blocks, switch cases, labeled statements
Program
Output
undefined
function
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · high
The fix hoists a function declaration out of an else block into a switch case clause, where function declarations are not allowed in strict mode and have implementation-dependent semantics in sloppy mode. Before the fix the function was never created (the else was dead code), so typeof g yielded 'undefined'; after the fix the function is created (or a syntax error occurs), changing the observable behavior.
Explanation Nemotron 3 Super unverified
The original `else` block defines `g` only when the condition is false—here always executed because `if(false)` never runs—but as a function declaration inside a block, it remains scoped to that block in strict mode, making `g` inaccessible outside. After rewriting, `g` becomes a top-level function declaration within the same block scope but now hoisted to the block’s start, still confined to the block. However, JavaScript treats block-scoped function declarations inconsistently across engines; here, the engine likely hoists `g` to the function scope of `main`, making it accessible for `typeof`. Thus, `typeof g` changes from `undefined` (original, due to block scoping) to `function` (rewritten, due to hoisting to outer scope). This alters observable behavior.
Reproduce
- file
prog.js(the before program)- minimized program
- r1-p008.js
- evidence sheet
- r1-p008.md
- regression fixture
- r1-p008.js the minimized program with a header stating the observed change, for the tool's test suite
node prog.js bunx @biomejs/biome lint --only=style/noUselessElse --write prog.js node prog.js
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
noUselessElse fix · style noUselessElse conditional block · else clause containing function declaration · switch case if-else refactoring
- duplicate biomejs/biome/issues/11937 same rule noUselessElse hoisting a function declaration out of an else block into a switch case, colliding with an outer binding and changing typeof g from undefined to function
- related biomejs/biome/issues/3770 same rule noUselessElse but about a useful else with break in a for loop, not a function declaration hoisting in a switch case
- related biomejs/biome/issues/1191 same rule noUselessElse but about an else-if chain in object pattern matching, not a function declaration hoisting in a switch case
- related biomejs/biome/issues/4354 same rule noUselessElse but about not respecting else-if conditional, not a function declaration hoisting in a switch case
Details
- program
- Block-scoped function in switch
- hazard
- function declarations inside blocks, switch cases, labeled statements
- oracle
stdout before: undefined stdout after: function- run
- 2026-10-17T19-42-12-619Z-e4vp-biome-style_noUselessElse
generated program (10 lines) and the fix's diff
--- orig.js 2026-10-17 15:42:23.938505817 -0400 +++ fixed.js 2026-10-17 15:42:24.206500254 -0400 @@ -2,7 +2,7 @@ switch (0) { case 0: if (false) { return; } - else { function g() { return 2; } } + function g() { return 2; } console.log(typeof g); break; }
rule documentation given to the models
Summary
- Name: noUselessElse
- Fix: safe
- Default severity: info
- Available from version: 1.3.0
- Diagnostic category: lint/style/noUselessElse
Description
Disallow `else` block when the `if` block breaks early.
If an `if` block breaks early using a breaking statement (`return`, `break`, `continue`, or `throw`),
then the `else` block becomes useless.
Its contents can be placed outside of the block.
If an `if` block breaks early using a breaking statement (`return`, `break`, `continue`, or `throw`),
then the `else` block becomes unnecessary.
This is because the content of the `else` block will never be executed in conjunction with the `if` block,
as the breaking statement ensures the control flow exits the `if` block immediately.
Therefore, the `else` block is redundant, and its content can be placed outside of the block,
reducing the indentation level by one.
Examples
Invalid
```js,expect_diagnostic
while (x > 0) {
if (f(x)) {
break;
} else {
x++
}
}
```
```js,expect_diagnostic
function f(x) {
if (x < 0) {
return 0;
} else {
return x;
}
}
```
```js,expect_diagnostic
function f(x) {
if (x < 0) {
throw new RangeError();
} else {
return x;
}
}
```
Valid
```js
function f(x) {
if (x < 0) {
return 0;
}
return x;
}
```
```js
function f(x) {
if (x < 0) {
console.info("negative number");
} else if (x > 0) {
return x;
} else {
console.info("number 0");
}
}
```