biome correctness/noUnusedLabels
labelled safe
Analysis Nemotron 3 Super
The rule flags labeled statements where the label is never referenced by any break or continue statement within its scope.
Fix: The autofix removes the unused label and its trailing colon, leaving only the underlying statement unchanged.
12 hazards
- Removing a label before a block statement may change the interpretation of break/continue targets in nested loops if those inner statements rely on the outer label for control flow.
- If the labeled statement is a function declaration, removing the label could cause a syntax error because labels are not permitted on function declarations in strict mode.
- When the labeled statement is an empty block ({}), removing the label may drop a comment attached to the label token, altering source formatting.
- In a labeled switch statement, removing the label could break if a nested switch uses the same label name via a continue statement (though continue doesn't apply to switch, this highlights label name reuse confusion).
- If the label appears before a with statement, removing it might affect lexical scoping expectations in non-strict mode, though with is deprecated.
- For a labeled debugger statement, removing the label has no semantic effect but may interfere with debugging tools that associate labels with breakpoints.
- If the labeled statement is preceded by a line comment on the same line, the autofix may inadvertently remove that comment if it is token-attached to the label.
- In a labeled expression statement (e.g., LABEL: x = 1;), removing the label is safe, but if the expression has side effects, the timing remains unchanged—however, tools relying on label metadata for profiling could be affected.
- When the labeled statement is a class declaration, removing the label causes a syntax error because labels are not allowed on class declarations.
- If the label is used as a target by a break in a dynamically scoped eval string, removing it breaks the eval's control flow (though eval is discouraged).
- In a labeled loop containing a function with a break that closes over the label, removing the label breaks the inner function's control flow if the break is not removed (but the rule only fires when unused, so this case shouldn't occur—still, hypothetical misuse matters).
- If the label is immediately followed by a newline and a comment on the next line, the autofix preserves the comment, but if the tool incorrectly joins lines, it could alter comment placement.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | invalid | Hazard 1: Label captured by closure via break | In a labeled loop containing a function with a break that closes over the label, removing the label breaks the inner function's control flow if the break is not removed. |
| r1-p002 | invalid | Hazard 2: Label on class declaration causing syntax error after fix | When the labeled statement is a class declaration, removing the label causes a syntax error because labels are not allowed on class declarations. |
| r1-p003 | invalid | Hazard 3: Class elements interaction (fields, static block) | class fields, static blocks, private names, super calls |
| r1-p004 | invalid | Hazard 4: Getter/setter and defineProperty side effects | getters, setters and Object.defineProperty side effects |
| r1-p005 | fix ok | Hazard 5: This binding in arrow vs function methods | this binding: arrow vs function, methods extracted from objects, call/apply/bind |
| r1-p006 | silent prediction off | Hazard 6: Line comment attached to label removed by autofix | If the labeled statement is preceded by a line comment on the same line, the autofix may inadvertently remove that comment if it is token-attached to the label. |
| r1-p007 | fix ok | Hazard 7: Name collision after label removal causes shadowing | name collisions across scopes after a move (shadowing) |
| r1-p008 | fix ok | Hazard 8: Var hoisting and redeclaration inside loop | var hoisting and re-declaration inside loops or after use |
| r2-p001 | fix ok | Hazard 1: Comment preservation after label | Line comment after label may be mishandled during autofix |
| r2-p002 | invalid | Hazard 2: Label on class declaration | Label on class declaration causes syntax error after removal |
| r2-p003 | fix ok | Hazard 3: Break in eval string referencing label | Break in eval string depends on label existence |
| r2-p004 | fix ok prediction off | Hazard 4: Null/undefined distinction with optional chaining | Optional chaining short-circuit behavior under label |
| r2-p005 | invalid | Hazard 5: Label on function declaration | Label on function declaration invalid in strict mode |
| r2-p006 | fix ok prediction off | Hazard 6: Numeric/string coercion edge cases | Coercion behavior in labeled expression |
| r2-p007 | fix ok | Hazard 7: This binding in arrow vs function methods | This binding affected by label removal in method context |
| r2-p008 | fix ok | Hazard 8: Function declarations inside labeled blocks | Function declaration in labeled block interacts with scope |
Sources
r1-p001 · Hazard 1: Label captured by closure via break (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-45-5)
1OUTER: {
2 const fn = () => { break OUTER; };
3 fn();
4}
5console.log('reached');
r1-p002 · Hazard 2: Label on class declaration causing syntax error after fix (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-45-5)
1MYLABEL: class Test {};
r1-p003 · Hazard 3: Class elements interaction (fields, static block) (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-45-5)
1LOOP: class C {
2 static field = 1;
3 #private = 2;
4 static { console.log('static'); }
5 constructor() { console.log(super ? 'has super' : 'no super'); }
6}
7new C();
r1-p004 · Hazard 4: Getter/setter and defineProperty side effects (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-45-5)
1LABEL: let obj = {
2 get x() { return 1; },
3 set x(v) { console.log('set', v); }
4};
5Object.defineProperty(obj, 'y', { value: 2 });
6console.log(obj.x, obj.y);
r1-p005 · Hazard 5: This binding in arrow vs function methods
1THISLABEL: {
2 const obj = {
3 val: 42,
4 fn: function() { return this.val; },
5 arr: () => this.val
6 };
7 console.log(obj.fn(), obj.arr());
8 const f = obj.fn;
9 const a = obj.arr;
10 console.log(f.call(obj), a.call(obj));
11}
--- orig.js 2026-10-17 16:46:02.254726081 -0400 +++ fixed.js 2026-10-17 16:46:02.530733259 -0400 @@ -1,4 +1,4 @@ -THISLABEL: { +{ const obj = { val: 42, fn: function() { return this.val; },
r1-p006 · Hazard 6: Line comment attached to label removed by autofix
1// important: LABEL: console.log('hello');
2console.log('done');
done
r1-p007 · Hazard 7: Name collision after label removal causes shadowing
1SHADOW: {
2 let SHADOW = 1;
3 console.log(SHADOW);
4 {
5 let SHADOW = 2;
6 console.log(SHADOW);
7 }
8}
--- orig.js 2026-10-17 16:46:02.921743429 -0400 +++ fixed.js 2026-10-17 16:46:03.192750471 -0400 @@ -1,4 +1,4 @@ -SHADOW: { +{ let SHADOW = 1; console.log(SHADOW); {
1 2
r1-p008 · Hazard 8: Var hoisting and redeclaration inside loop
1VARLOOP: for (var i = 0; i < 2; i++) {
2 var x = i;
3 console.log(x);
4}
5console.log(typeof x, typeof i);
--- orig.js 2026-10-17 16:46:03.357754757 -0400 +++ fixed.js 2026-10-17 16:46:03.630761848 -0400 @@ -1,4 +1,4 @@ -VARLOOP: for (var i = 0; i < 2; i++) { +for (var i = 0; i < 2; i++) { var x = i; console.log(x); }
0 1 number number
r2-p001 · Hazard 1: Comment preservation after label
1// Label here
2OUTER: // comment after label
3while (false) { }
4console.log('done');
--- orig.js 2026-10-17 16:46:07.848871109 -0400 +++ fixed.js 2026-10-17 16:46:08.135878523 -0400 @@ -1,4 +1,3 @@ // Label here -OUTER: // comment after label while (false) { } console.log('done');
done
r2-p002 · Hazard 2: Label on class declaration (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-45-5)
1CLASS: class C { constructor() { this.x = 1; } }
2try {
3 new C();
4 console.log('ok');
5} catch (e) {
6 console.log(e.name + ': ' + e.message);
7}
r2-p003 · Hazard 3: Break in eval string referencing label
1LOOP: for (let i = 0; i < 3; i++) {
2 if (i === 1) eval('break LOOP;');
3 console.log(i);
4}
5console.log('after loop');
--- orig.js 2026-10-17 16:46:08.341883840 -0400 +++ fixed.js 2026-10-17 16:46:08.616890939 -0400 @@ -1,4 +1,4 @@ -LOOP: for (let i = 0; i < 3; i++) { +for (let i = 0; i < 3; i++) { if (i === 1) eval('break LOOP;'); console.log(i); }
0
r2-p004 · Hazard 4: Null/undefined distinction with optional chaining
1LABEL: {
2 const obj = null;
3 const val = obj?.prop ?? 'default';
4 console.log(val);
5}
--- orig.js 2026-10-17 16:46:08.796895586 -0400 +++ fixed.js 2026-10-17 16:46:09.081902940 -0400 @@ -1,4 +1,4 @@ -LABEL: { +{ const obj = null; const val = obj?.prop ?? 'default'; console.log(val);
default
r2-p005 · Hazard 5: Label on function declaration (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-45-5)
1"use strict";
2FUNC: function f() { return 42; }
3try {
4 console.log(f());
5} catch (e) {
6 console.log(e.name + ': ' + e.message);
7}
r2-p006 · Hazard 6: Numeric/string coercion edge cases
1LABEL: {
2 const x = 0;
3 const y = '';
4 console.log(+x, +y);
5 console.log(String(x), String(y));
6}
--- orig.js 2026-10-17 16:46:09.315908973 -0400 +++ fixed.js 2026-10-17 16:46:09.602916373 -0400 @@ -1,4 +1,4 @@ -LABEL: { +{ const x = 0; const y = ''; console.log(+x, +y);
0 0 0
r2-p007 · Hazard 7: This binding in arrow vs function methods
1OBJ: {
2 const obj = { value: 10, getValue: function() { return this.value; } };
3 const fn = obj.getValue;
4 console.log(obj.getValue(), fn());
5}
--- orig.js 2026-10-17 16:46:09.782921014 -0400 +++ fixed.js 2026-10-17 16:46:10.072928488 -0400 @@ -1,4 +1,4 @@ -OBJ: { +{ const obj = { value: 10, getValue: function() { return this.value; } }; const fn = obj.getValue; console.log(obj.getValue(), fn());
r2-p008 · Hazard 8: Function declarations inside labeled blocks
1SCOPE: {
2 if (true) {
3 function inner() { return 99; }
4 console.log(inner());
5 }
6 console.log(typeof inner);
7}
--- orig.js 2026-10-17 16:46:10.269933561 -0400 +++ fixed.js 2026-10-17 16:46:10.572941363 -0400 @@ -1,4 +1,4 @@ -SCOPE: { +{ if (true) { function inner() { return 99; } console.log(inner());
99 undefined