Skip to content

Commit 7f802bb

Browse files
authored
Fixed an issue with for statement's incrementor missing continue's control flow information (#60950)
1 parent b886b48 commit 7f802bb

5 files changed

+277
-1
lines changed

src/compiler/binder.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1536,13 +1536,16 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
15361536
function bindForStatement(node: ForStatement): void {
15371537
const preLoopLabel = setContinueTarget(node, createLoopLabel());
15381538
const preBodyLabel = createBranchLabel();
1539+
const preIncrementorLabel = createBranchLabel();
15391540
const postLoopLabel = createBranchLabel();
15401541
bind(node.initializer);
15411542
addAntecedent(preLoopLabel, currentFlow);
15421543
currentFlow = preLoopLabel;
15431544
bindCondition(node.condition, preBodyLabel, postLoopLabel);
15441545
currentFlow = finishFlowLabel(preBodyLabel);
1545-
bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel);
1546+
bindIterativeStatement(node.statement, postLoopLabel, preIncrementorLabel);
1547+
addAntecedent(preIncrementorLabel, currentFlow);
1548+
currentFlow = finishFlowLabel(preIncrementorLabel);
15461549
bind(node.incrementor);
15471550
addAntecedent(preLoopLabel, currentFlow);
15481551
currentFlow = finishFlowLabel(postLoopLabel);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
controlFlowForStatementContinueIntoIncrementor1.ts(8,5): error TS2322: Type 'string | number' is not assignable to type 'number'.
2+
Type 'string' is not assignable to type 'number'.
3+
controlFlowForStatementContinueIntoIncrementor1.ts(23,5): error TS2322: Type 'string | number' is not assignable to type 'number'.
4+
Type 'string' is not assignable to type 'number'.
5+
6+
7+
==== controlFlowForStatementContinueIntoIncrementor1.ts (2 errors) ====
8+
// https://github.com/microsoft/TypeScript/issues/60945
9+
10+
{
11+
let iNext;
12+
for (
13+
let i = 0;
14+
i < 10;
15+
i = iNext // error
16+
~
17+
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
18+
!!! error TS2322: Type 'string' is not assignable to type 'number'.
19+
) {
20+
if (i == 5) {
21+
iNext = "bad";
22+
continue;
23+
}
24+
iNext = i + 1;
25+
}
26+
}
27+
28+
{
29+
let iNext: string | number = "";
30+
for (
31+
let i = 0;
32+
i < 10;
33+
i = iNext // error
34+
~
35+
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
36+
!!! error TS2322: Type 'string' is not assignable to type 'number'.
37+
) {
38+
if (i == 5) {
39+
iNext = "bad";
40+
continue;
41+
}
42+
iNext = i + 1;
43+
}
44+
}
45+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//// [tests/cases/compiler/controlFlowForStatementContinueIntoIncrementor1.ts] ////
2+
3+
=== controlFlowForStatementContinueIntoIncrementor1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/60945
5+
6+
{
7+
let iNext;
8+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))
9+
10+
for (
11+
let i = 0;
12+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
13+
14+
i < 10;
15+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
16+
17+
i = iNext // error
18+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
19+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))
20+
21+
) {
22+
if (i == 5) {
23+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
24+
25+
iNext = "bad";
26+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))
27+
28+
continue;
29+
}
30+
iNext = i + 1;
31+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))
32+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
33+
}
34+
}
35+
36+
{
37+
let iNext: string | number = "";
38+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))
39+
40+
for (
41+
let i = 0;
42+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
43+
44+
i < 10;
45+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
46+
47+
i = iNext // error
48+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
49+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))
50+
51+
) {
52+
if (i == 5) {
53+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
54+
55+
iNext = "bad";
56+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))
57+
58+
continue;
59+
}
60+
iNext = i + 1;
61+
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))
62+
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
63+
}
64+
}
65+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//// [tests/cases/compiler/controlFlowForStatementContinueIntoIncrementor1.ts] ////
2+
3+
=== controlFlowForStatementContinueIntoIncrementor1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/60945
5+
6+
{
7+
let iNext;
8+
>iNext : any
9+
> : ^^^
10+
11+
for (
12+
let i = 0;
13+
>i : number
14+
> : ^^^^^^
15+
>0 : 0
16+
> : ^
17+
18+
i < 10;
19+
>i < 10 : boolean
20+
> : ^^^^^^^
21+
>i : number
22+
> : ^^^^^^
23+
>10 : 10
24+
> : ^^
25+
26+
i = iNext // error
27+
>i = iNext : string | number
28+
> : ^^^^^^^^^^^^^^^
29+
>i : number
30+
> : ^^^^^^
31+
>iNext : string | number
32+
> : ^^^^^^^^^^^^^^^
33+
34+
) {
35+
if (i == 5) {
36+
>i == 5 : boolean
37+
> : ^^^^^^^
38+
>i : number
39+
> : ^^^^^^
40+
>5 : 5
41+
> : ^
42+
43+
iNext = "bad";
44+
>iNext = "bad" : "bad"
45+
> : ^^^^^
46+
>iNext : any
47+
> : ^^^
48+
>"bad" : "bad"
49+
> : ^^^^^
50+
51+
continue;
52+
}
53+
iNext = i + 1;
54+
>iNext = i + 1 : number
55+
> : ^^^^^^
56+
>iNext : any
57+
> : ^^^
58+
>i + 1 : number
59+
> : ^^^^^^
60+
>i : number
61+
> : ^^^^^^
62+
>1 : 1
63+
> : ^
64+
}
65+
}
66+
67+
{
68+
let iNext: string | number = "";
69+
>iNext : string | number
70+
> : ^^^^^^^^^^^^^^^
71+
>"" : ""
72+
> : ^^
73+
74+
for (
75+
let i = 0;
76+
>i : number
77+
> : ^^^^^^
78+
>0 : 0
79+
> : ^
80+
81+
i < 10;
82+
>i < 10 : boolean
83+
> : ^^^^^^^
84+
>i : number
85+
> : ^^^^^^
86+
>10 : 10
87+
> : ^^
88+
89+
i = iNext // error
90+
>i = iNext : string | number
91+
> : ^^^^^^^^^^^^^^^
92+
>i : number
93+
> : ^^^^^^
94+
>iNext : string | number
95+
> : ^^^^^^^^^^^^^^^
96+
97+
) {
98+
if (i == 5) {
99+
>i == 5 : boolean
100+
> : ^^^^^^^
101+
>i : number
102+
> : ^^^^^^
103+
>5 : 5
104+
> : ^
105+
106+
iNext = "bad";
107+
>iNext = "bad" : "bad"
108+
> : ^^^^^
109+
>iNext : string | number
110+
> : ^^^^^^^^^^^^^^^
111+
>"bad" : "bad"
112+
> : ^^^^^
113+
114+
continue;
115+
}
116+
iNext = i + 1;
117+
>iNext = i + 1 : number
118+
> : ^^^^^^
119+
>iNext : string | number
120+
> : ^^^^^^^^^^^^^^^
121+
>i + 1 : number
122+
> : ^^^^^^
123+
>i : number
124+
> : ^^^^^^
125+
>1 : 1
126+
> : ^
127+
}
128+
}
129+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/TypeScript/issues/60945
5+
6+
{
7+
let iNext;
8+
for (
9+
let i = 0;
10+
i < 10;
11+
i = iNext // error
12+
) {
13+
if (i == 5) {
14+
iNext = "bad";
15+
continue;
16+
}
17+
iNext = i + 1;
18+
}
19+
}
20+
21+
{
22+
let iNext: string | number = "";
23+
for (
24+
let i = 0;
25+
i < 10;
26+
i = iNext // error
27+
) {
28+
if (i == 5) {
29+
iNext = "bad";
30+
continue;
31+
}
32+
iNext = i + 1;
33+
}
34+
}

0 commit comments

Comments
 (0)