Skip to content

Commit 4ec6989

Browse files
Port PR #61376: Fix spurious "used before being assigned" errors in for of/in loops (#2462)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
1 parent 01cac67 commit 4ec6989

5 files changed

Lines changed: 416 additions & 3 deletions

File tree

internal/checker/checker.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10831,9 +10831,9 @@ func (c *Checker) checkIdentifier(node *ast.Node, checkMode CheckMode) *Type {
1083110831
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
1083210832
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
1083310833
// declaration container are the same).
10834-
isNeverInitialized := immediateDeclaration != nil && ast.IsVariableDeclaration(immediateDeclaration) && immediateDeclaration.Initializer() == nil &&
10835-
immediateDeclaration.AsVariableDeclaration().ExclamationToken == nil && c.isMutableLocalVariableDeclaration(immediateDeclaration) &&
10836-
!c.isSymbolAssignedDefinitely(symbol)
10834+
isNeverInitialized := immediateDeclaration != nil && ast.IsVariableDeclaration(immediateDeclaration) && !ast.IsForInOrOfStatement(immediateDeclaration.Parent.Parent) &&
10835+
immediateDeclaration.Initializer() == nil && immediateDeclaration.AsVariableDeclaration().ExclamationToken == nil &&
10836+
c.isMutableLocalVariableDeclaration(immediateDeclaration) && !c.isSymbolAssignedDefinitely(symbol)
1083710837
assumeInitialized := isParameter ||
1083810838
isAlias ||
1083910839
(isOuterVariable && !isNeverInitialized) ||
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
unusedLocalsInForInOrOf1.ts(2,12): error TS6133: 'f' is declared but its value is never read.
2+
unusedLocalsInForInOrOf1.ts(8,7): error TS6133: 'f' is declared but its value is never read.
3+
unusedLocalsInForInOrOf1.ts(14,12): error TS6133: 'g' is declared but its value is never read.
4+
unusedLocalsInForInOrOf1.ts(20,12): error TS6133: 'f2' is declared but its value is never read.
5+
unusedLocalsInForInOrOf1.ts(26,7): error TS6133: 'f2' is declared but its value is never read.
6+
unusedLocalsInForInOrOf1.ts(32,12): error TS6133: 'g2' is declared but its value is never read.
7+
unusedLocalsInForInOrOf1.ts(38,12): error TS6133: 'f3' is declared but its value is never read.
8+
unusedLocalsInForInOrOf1.ts(44,7): error TS6133: 'f3' is declared but its value is never read.
9+
unusedLocalsInForInOrOf1.ts(50,12): error TS6133: 'g3' is declared but its value is never read.
10+
11+
12+
==== unusedLocalsInForInOrOf1.ts (9 errors) ====
13+
for (let x of [1, 2]) {
14+
function f() {
15+
~
16+
!!! error TS6133: 'f' is declared but its value is never read.
17+
x;
18+
}
19+
}
20+
21+
for (let x of [1, 2]) {
22+
let f = () => {
23+
~
24+
!!! error TS6133: 'f' is declared but its value is never read.
25+
x;
26+
};
27+
}
28+
29+
for (const x of [1, 2]) {
30+
function g() {
31+
~
32+
!!! error TS6133: 'g' is declared but its value is never read.
33+
x;
34+
}
35+
}
36+
37+
for (let x in { a: 1, b: 2 }) {
38+
function f2() {
39+
~~
40+
!!! error TS6133: 'f2' is declared but its value is never read.
41+
x;
42+
}
43+
}
44+
45+
for (let x in { a: 1, b: 2 }) {
46+
let f2 = () => {
47+
~~
48+
!!! error TS6133: 'f2' is declared but its value is never read.
49+
x;
50+
};
51+
}
52+
53+
for (const x in { a: 1, b: 2 }) {
54+
function g2() {
55+
~~
56+
!!! error TS6133: 'g2' is declared but its value is never read.
57+
x;
58+
}
59+
}
60+
61+
for (let { x } of [{ x: 1 }, { x: 2 }]) {
62+
function f3() {
63+
~~
64+
!!! error TS6133: 'f3' is declared but its value is never read.
65+
x;
66+
}
67+
}
68+
69+
for (let { x } of [{ x: 1 }, { x: 2 }]) {
70+
let f3 = () => {
71+
~~
72+
!!! error TS6133: 'f3' is declared but its value is never read.
73+
x;
74+
};
75+
}
76+
77+
for (const { x } of [{ x: 1 }, { x: 2 }]) {
78+
function g3() {
79+
~~
80+
!!! error TS6133: 'g3' is declared but its value is never read.
81+
x;
82+
}
83+
}
84+
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//// [tests/cases/compiler/unusedLocalsInForInOrOf1.ts] ////
2+
3+
=== unusedLocalsInForInOrOf1.ts ===
4+
for (let x of [1, 2]) {
5+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 0, 8))
6+
7+
function f() {
8+
>f : Symbol(f, Decl(unusedLocalsInForInOrOf1.ts, 0, 23))
9+
10+
x;
11+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 0, 8))
12+
}
13+
}
14+
15+
for (let x of [1, 2]) {
16+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 6, 8))
17+
18+
let f = () => {
19+
>f : Symbol(f, Decl(unusedLocalsInForInOrOf1.ts, 7, 5))
20+
21+
x;
22+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 6, 8))
23+
24+
};
25+
}
26+
27+
for (const x of [1, 2]) {
28+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 12, 10))
29+
30+
function g() {
31+
>g : Symbol(g, Decl(unusedLocalsInForInOrOf1.ts, 12, 25))
32+
33+
x;
34+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 12, 10))
35+
}
36+
}
37+
38+
for (let x in { a: 1, b: 2 }) {
39+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 18, 8))
40+
>a : Symbol(a, Decl(unusedLocalsInForInOrOf1.ts, 18, 15))
41+
>b : Symbol(b, Decl(unusedLocalsInForInOrOf1.ts, 18, 21))
42+
43+
function f2() {
44+
>f2 : Symbol(f2, Decl(unusedLocalsInForInOrOf1.ts, 18, 31))
45+
46+
x;
47+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 18, 8))
48+
}
49+
}
50+
51+
for (let x in { a: 1, b: 2 }) {
52+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 24, 8))
53+
>a : Symbol(a, Decl(unusedLocalsInForInOrOf1.ts, 24, 15))
54+
>b : Symbol(b, Decl(unusedLocalsInForInOrOf1.ts, 24, 21))
55+
56+
let f2 = () => {
57+
>f2 : Symbol(f2, Decl(unusedLocalsInForInOrOf1.ts, 25, 5))
58+
59+
x;
60+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 24, 8))
61+
62+
};
63+
}
64+
65+
for (const x in { a: 1, b: 2 }) {
66+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 30, 10))
67+
>a : Symbol(a, Decl(unusedLocalsInForInOrOf1.ts, 30, 17))
68+
>b : Symbol(b, Decl(unusedLocalsInForInOrOf1.ts, 30, 23))
69+
70+
function g2() {
71+
>g2 : Symbol(g2, Decl(unusedLocalsInForInOrOf1.ts, 30, 33))
72+
73+
x;
74+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 30, 10))
75+
}
76+
}
77+
78+
for (let { x } of [{ x: 1 }, { x: 2 }]) {
79+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 10))
80+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 20))
81+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 30))
82+
83+
function f3() {
84+
>f3 : Symbol(f3, Decl(unusedLocalsInForInOrOf1.ts, 36, 41))
85+
86+
x;
87+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 36, 10))
88+
}
89+
}
90+
91+
for (let { x } of [{ x: 1 }, { x: 2 }]) {
92+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 10))
93+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 20))
94+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 30))
95+
96+
let f3 = () => {
97+
>f3 : Symbol(f3, Decl(unusedLocalsInForInOrOf1.ts, 43, 5))
98+
99+
x;
100+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 42, 10))
101+
102+
};
103+
}
104+
105+
for (const { x } of [{ x: 1 }, { x: 2 }]) {
106+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 12))
107+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 22))
108+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 32))
109+
110+
function g3() {
111+
>g3 : Symbol(g3, Decl(unusedLocalsInForInOrOf1.ts, 48, 43))
112+
113+
x;
114+
>x : Symbol(x, Decl(unusedLocalsInForInOrOf1.ts, 48, 12))
115+
}
116+
}
117+
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
//// [tests/cases/compiler/unusedLocalsInForInOrOf1.ts] ////
2+
3+
=== unusedLocalsInForInOrOf1.ts ===
4+
for (let x of [1, 2]) {
5+
>x : number
6+
>[1, 2] : number[]
7+
>1 : 1
8+
>2 : 2
9+
10+
function f() {
11+
>f : () => void
12+
13+
x;
14+
>x : number
15+
}
16+
}
17+
18+
for (let x of [1, 2]) {
19+
>x : number
20+
>[1, 2] : number[]
21+
>1 : 1
22+
>2 : 2
23+
24+
let f = () => {
25+
>f : () => void
26+
>() => { x; } : () => void
27+
28+
x;
29+
>x : number
30+
31+
};
32+
}
33+
34+
for (const x of [1, 2]) {
35+
>x : number
36+
>[1, 2] : number[]
37+
>1 : 1
38+
>2 : 2
39+
40+
function g() {
41+
>g : () => void
42+
43+
x;
44+
>x : number
45+
}
46+
}
47+
48+
for (let x in { a: 1, b: 2 }) {
49+
>x : string
50+
>{ a: 1, b: 2 } : { a: number; b: number; }
51+
>a : number
52+
>1 : 1
53+
>b : number
54+
>2 : 2
55+
56+
function f2() {
57+
>f2 : () => void
58+
59+
x;
60+
>x : string
61+
}
62+
}
63+
64+
for (let x in { a: 1, b: 2 }) {
65+
>x : string
66+
>{ a: 1, b: 2 } : { a: number; b: number; }
67+
>a : number
68+
>1 : 1
69+
>b : number
70+
>2 : 2
71+
72+
let f2 = () => {
73+
>f2 : () => void
74+
>() => { x; } : () => void
75+
76+
x;
77+
>x : string
78+
79+
};
80+
}
81+
82+
for (const x in { a: 1, b: 2 }) {
83+
>x : string
84+
>{ a: 1, b: 2 } : { a: number; b: number; }
85+
>a : number
86+
>1 : 1
87+
>b : number
88+
>2 : 2
89+
90+
function g2() {
91+
>g2 : () => void
92+
93+
x;
94+
>x : string
95+
}
96+
}
97+
98+
for (let { x } of [{ x: 1 }, { x: 2 }]) {
99+
>x : number
100+
>[{ x: 1 }, { x: 2 }] : { x: number; }[]
101+
>{ x: 1 } : { x: number; }
102+
>x : number
103+
>1 : 1
104+
>{ x: 2 } : { x: number; }
105+
>x : number
106+
>2 : 2
107+
108+
function f3() {
109+
>f3 : () => void
110+
111+
x;
112+
>x : number
113+
}
114+
}
115+
116+
for (let { x } of [{ x: 1 }, { x: 2 }]) {
117+
>x : number
118+
>[{ x: 1 }, { x: 2 }] : { x: number; }[]
119+
>{ x: 1 } : { x: number; }
120+
>x : number
121+
>1 : 1
122+
>{ x: 2 } : { x: number; }
123+
>x : number
124+
>2 : 2
125+
126+
let f3 = () => {
127+
>f3 : () => void
128+
>() => { x; } : () => void
129+
130+
x;
131+
>x : number
132+
133+
};
134+
}
135+
136+
for (const { x } of [{ x: 1 }, { x: 2 }]) {
137+
>x : number
138+
>[{ x: 1 }, { x: 2 }] : { x: number; }[]
139+
>{ x: 1 } : { x: number; }
140+
>x : number
141+
>1 : 1
142+
>{ x: 2 } : { x: number; }
143+
>x : number
144+
>2 : 2
145+
146+
function g3() {
147+
>g3 : () => void
148+
149+
x;
150+
>x : number
151+
}
152+
}
153+

0 commit comments

Comments
 (0)