diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 0ef37ebeca6..b62c619c333 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -10806,9 +10806,9 @@ func (c *Checker) checkIdentifier(node *ast.Node, checkMode CheckMode) *Type { // We only look for uninitialized variables in strict null checking mode, and only when we can analyze // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). - isNeverInitialized := immediateDeclaration != nil && ast.IsVariableDeclaration(immediateDeclaration) && immediateDeclaration.Initializer() == nil && - immediateDeclaration.AsVariableDeclaration().ExclamationToken == nil && c.isMutableLocalVariableDeclaration(immediateDeclaration) && - !c.isSymbolAssignedDefinitely(symbol) + isNeverInitialized := immediateDeclaration != nil && ast.IsVariableDeclaration(immediateDeclaration) && !ast.IsForInOrOfStatement(immediateDeclaration.Parent.Parent) && + immediateDeclaration.Initializer() == nil && immediateDeclaration.AsVariableDeclaration().ExclamationToken == nil && + c.isMutableLocalVariableDeclaration(immediateDeclaration) && !c.isSymbolAssignedDefinitely(symbol) assumeInitialized := isParameter || isAlias || (isOuterVariable && !isNeverInitialized) || diff --git a/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.errors.txt b/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.errors.txt new file mode 100644 index 00000000000..2b0a014ec96 --- /dev/null +++ b/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.errors.txt @@ -0,0 +1,84 @@ +unusedLocalsInForInOrOf1.ts(2,12): error TS6133: 'f' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(8,7): error TS6133: 'f' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(14,12): error TS6133: 'g' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(20,12): error TS6133: 'f2' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(26,7): error TS6133: 'f2' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(32,12): error TS6133: 'g2' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(38,12): error TS6133: 'f3' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(44,7): error TS6133: 'f3' is declared but its value is never read. +unusedLocalsInForInOrOf1.ts(50,12): error TS6133: 'g3' is declared but its value is never read. + + +==== unusedLocalsInForInOrOf1.ts (9 errors) ==== + for (let x of [1, 2]) { + function f() { + ~ +!!! error TS6133: 'f' is declared but its value is never read. + x; + } + } + + for (let x of [1, 2]) { + let f = () => { + ~ +!!! error TS6133: 'f' is declared but its value is never read. + x; + }; + } + + for (const x of [1, 2]) { + function g() { + ~ +!!! error TS6133: 'g' is declared but its value is never read. + x; + } + } + + for (let x in { a: 1, b: 2 }) { + function f2() { + ~~ +!!! error TS6133: 'f2' is declared but its value is never read. + x; + } + } + + for (let x in { a: 1, b: 2 }) { + let f2 = () => { + ~~ +!!! error TS6133: 'f2' is declared but its value is never read. + x; + }; + } + + for (const x in { a: 1, b: 2 }) { + function g2() { + ~~ +!!! error TS6133: 'g2' is declared but its value is never read. + x; + } + } + + for (let { x } of [{ x: 1 }, { x: 2 }]) { + function f3() { + ~~ +!!! error TS6133: 'f3' is declared but its value is never read. + x; + } + } + + for (let { x } of [{ x: 1 }, { x: 2 }]) { + let f3 = () => { + ~~ +!!! error TS6133: 'f3' is declared but its value is never read. + x; + }; + } + + for (const { x } of [{ x: 1 }, { x: 2 }]) { + function g3() { + ~~ +!!! error TS6133: 'g3' is declared but its value is never read. + x; + } + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.symbols b/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.symbols new file mode 100644 index 00000000000..c4c2381baff --- /dev/null +++ b/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.symbols @@ -0,0 +1,117 @@ +//// [tests/cases/compiler/unusedLocalsInForInOrOf1.ts] //// + +=== unusedLocalsInForInOrOf1.ts === +for (let x of [1, 2]) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 0, 8)) + + function f() { +>f : Symbol(f, Decl(unusedLocalsInForInOrOf1.ts, 0, 23)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 0, 8)) + } +} + +for (let x of [1, 2]) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 6, 8)) + + let f = () => { +>f : Symbol(f, Decl(unusedLocalsInForInOrOf1.ts, 7, 5)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 6, 8)) + + }; +} + +for (const x of [1, 2]) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 12, 10)) + + function g() { +>g : Symbol(g, Decl(unusedLocalsInForInOrOf1.ts, 12, 25)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 12, 10)) + } +} + +for (let x in { a: 1, b: 2 }) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 18, 8)) +>a : Symbol(a, Decl(unusedLocalsInForInOrOf1.ts, 18, 15)) +>b : Symbol(b, Decl(unusedLocalsInForInOrOf1.ts, 18, 21)) + + function f2() { +>f2 : Symbol(f2, Decl(unusedLocalsInForInOrOf1.ts, 18, 31)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 18, 8)) + } +} + +for (let x in { a: 1, b: 2 }) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 24, 8)) +>a : Symbol(a, Decl(unusedLocalsInForInOrOf1.ts, 24, 15)) +>b : Symbol(b, Decl(unusedLocalsInForInOrOf1.ts, 24, 21)) + + let f2 = () => { +>f2 : Symbol(f2, Decl(unusedLocalsInForInOrOf1.ts, 25, 5)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 24, 8)) + + }; +} + +for (const x in { a: 1, b: 2 }) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 30, 10)) +>a : Symbol(a, Decl(unusedLocalsInForInOrOf1.ts, 30, 17)) +>b : Symbol(b, Decl(unusedLocalsInForInOrOf1.ts, 30, 23)) + + function g2() { +>g2 : Symbol(g2, Decl(unusedLocalsInForInOrOf1.ts, 30, 33)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 30, 10)) + } +} + +for (let { x } of [{ x: 1 }, { x: 2 }]) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 10)) +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 20)) +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 30)) + + function f3() { +>f3 : Symbol(f3, Decl(unusedLocalsInForInOrOf1.ts, 36, 41)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 10)) + } +} + +for (let { x } of [{ x: 1 }, { x: 2 }]) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 10)) +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 20)) +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 30)) + + let f3 = () => { +>f3 : Symbol(f3, Decl(unusedLocalsInForInOrOf1.ts, 43, 5)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 10)) + + }; +} + +for (const { x } of [{ x: 1 }, { x: 2 }]) { +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 12)) +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 22)) +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 32)) + + function g3() { +>g3 : Symbol(g3, Decl(unusedLocalsInForInOrOf1.ts, 48, 43)) + + x; +>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 12)) + } +} + diff --git a/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.types b/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.types new file mode 100644 index 00000000000..b891594c4b7 --- /dev/null +++ b/testdata/baselines/reference/compiler/unusedLocalsInForInOrOf1.types @@ -0,0 +1,153 @@ +//// [tests/cases/compiler/unusedLocalsInForInOrOf1.ts] //// + +=== unusedLocalsInForInOrOf1.ts === +for (let x of [1, 2]) { +>x : number +>[1, 2] : number[] +>1 : 1 +>2 : 2 + + function f() { +>f : () => void + + x; +>x : number + } +} + +for (let x of [1, 2]) { +>x : number +>[1, 2] : number[] +>1 : 1 +>2 : 2 + + let f = () => { +>f : () => void +>() => { x; } : () => void + + x; +>x : number + + }; +} + +for (const x of [1, 2]) { +>x : number +>[1, 2] : number[] +>1 : 1 +>2 : 2 + + function g() { +>g : () => void + + x; +>x : number + } +} + +for (let x in { a: 1, b: 2 }) { +>x : string +>{ a: 1, b: 2 } : { a: number; b: number; } +>a : number +>1 : 1 +>b : number +>2 : 2 + + function f2() { +>f2 : () => void + + x; +>x : string + } +} + +for (let x in { a: 1, b: 2 }) { +>x : string +>{ a: 1, b: 2 } : { a: number; b: number; } +>a : number +>1 : 1 +>b : number +>2 : 2 + + let f2 = () => { +>f2 : () => void +>() => { x; } : () => void + + x; +>x : string + + }; +} + +for (const x in { a: 1, b: 2 }) { +>x : string +>{ a: 1, b: 2 } : { a: number; b: number; } +>a : number +>1 : 1 +>b : number +>2 : 2 + + function g2() { +>g2 : () => void + + x; +>x : string + } +} + +for (let { x } of [{ x: 1 }, { x: 2 }]) { +>x : number +>[{ x: 1 }, { x: 2 }] : { x: number; }[] +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 +>{ x: 2 } : { x: number; } +>x : number +>2 : 2 + + function f3() { +>f3 : () => void + + x; +>x : number + } +} + +for (let { x } of [{ x: 1 }, { x: 2 }]) { +>x : number +>[{ x: 1 }, { x: 2 }] : { x: number; }[] +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 +>{ x: 2 } : { x: number; } +>x : number +>2 : 2 + + let f3 = () => { +>f3 : () => void +>() => { x; } : () => void + + x; +>x : number + + }; +} + +for (const { x } of [{ x: 1 }, { x: 2 }]) { +>x : number +>[{ x: 1 }, { x: 2 }] : { x: number; }[] +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 +>{ x: 2 } : { x: number; } +>x : number +>2 : 2 + + function g3() { +>g3 : () => void + + x; +>x : number + } +} + diff --git a/testdata/tests/cases/compiler/unusedLocalsInForInOrOf1.ts b/testdata/tests/cases/compiler/unusedLocalsInForInOrOf1.ts new file mode 100644 index 00000000000..edbdad5c590 --- /dev/null +++ b/testdata/tests/cases/compiler/unusedLocalsInForInOrOf1.ts @@ -0,0 +1,59 @@ +// @strict: true +// @target: esnext +// @noEmit: true +// @noUnusedLocals: true +// @noUnusedParameters: true + +for (let x of [1, 2]) { + function f() { + x; + } +} + +for (let x of [1, 2]) { + let f = () => { + x; + }; +} + +for (const x of [1, 2]) { + function g() { + x; + } +} + +for (let x in { a: 1, b: 2 }) { + function f2() { + x; + } +} + +for (let x in { a: 1, b: 2 }) { + let f2 = () => { + x; + }; +} + +for (const x in { a: 1, b: 2 }) { + function g2() { + x; + } +} + +for (let { x } of [{ x: 1 }, { x: 2 }]) { + function f3() { + x; + } +} + +for (let { x } of [{ x: 1 }, { x: 2 }]) { + let f3 = () => { + x; + }; +} + +for (const { x } of [{ x: 1 }, { x: 2 }]) { + function g3() { + x; + } +}