Skip to content

Commit

Permalink
Fixed an issue with for statement's incrementor missing continue's co…
Browse files Browse the repository at this point in the history
…ntrol flow information (#60950)
  • Loading branch information
Andarist authored Jan 22, 2025
1 parent b886b48 commit 7f802bb
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1536,13 +1536,16 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
function bindForStatement(node: ForStatement): void {
const preLoopLabel = setContinueTarget(node, createLoopLabel());
const preBodyLabel = createBranchLabel();
const preIncrementorLabel = createBranchLabel();
const postLoopLabel = createBranchLabel();
bind(node.initializer);
addAntecedent(preLoopLabel, currentFlow);
currentFlow = preLoopLabel;
bindCondition(node.condition, preBodyLabel, postLoopLabel);
currentFlow = finishFlowLabel(preBodyLabel);
bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel);
bindIterativeStatement(node.statement, postLoopLabel, preIncrementorLabel);
addAntecedent(preIncrementorLabel, currentFlow);
currentFlow = finishFlowLabel(preIncrementorLabel);
bind(node.incrementor);
addAntecedent(preLoopLabel, currentFlow);
currentFlow = finishFlowLabel(postLoopLabel);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
controlFlowForStatementContinueIntoIncrementor1.ts(8,5): error TS2322: Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
controlFlowForStatementContinueIntoIncrementor1.ts(23,5): error TS2322: Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.


==== controlFlowForStatementContinueIntoIncrementor1.ts (2 errors) ====
// https://github.com/microsoft/TypeScript/issues/60945

{
let iNext;
for (
let i = 0;
i < 10;
i = iNext // error
~
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
) {
if (i == 5) {
iNext = "bad";
continue;
}
iNext = i + 1;
}
}

{
let iNext: string | number = "";
for (
let i = 0;
i < 10;
i = iNext // error
~
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
) {
if (i == 5) {
iNext = "bad";
continue;
}
iNext = i + 1;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//// [tests/cases/compiler/controlFlowForStatementContinueIntoIncrementor1.ts] ////

=== controlFlowForStatementContinueIntoIncrementor1.ts ===
// https://github.com/microsoft/TypeScript/issues/60945

{
let iNext;
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))

for (
let i = 0;
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))

i < 10;
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))

i = iNext // error
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))

) {
if (i == 5) {
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))

iNext = "bad";
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))

continue;
}
iNext = i + 1;
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 3, 5))
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 5, 7))
}
}

{
let iNext: string | number = "";
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))

for (
let i = 0;
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))

i < 10;
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))

i = iNext // error
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))

) {
if (i == 5) {
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))

iNext = "bad";
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))

continue;
}
iNext = i + 1;
>iNext : Symbol(iNext, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 18, 5))
>i : Symbol(i, Decl(controlFlowForStatementContinueIntoIncrementor1.ts, 20, 7))
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
//// [tests/cases/compiler/controlFlowForStatementContinueIntoIncrementor1.ts] ////

=== controlFlowForStatementContinueIntoIncrementor1.ts ===
// https://github.com/microsoft/TypeScript/issues/60945

{
let iNext;
>iNext : any
> : ^^^

for (
let i = 0;
>i : number
> : ^^^^^^
>0 : 0
> : ^

i < 10;
>i < 10 : boolean
> : ^^^^^^^
>i : number
> : ^^^^^^
>10 : 10
> : ^^

i = iNext // error
>i = iNext : string | number
> : ^^^^^^^^^^^^^^^
>i : number
> : ^^^^^^
>iNext : string | number
> : ^^^^^^^^^^^^^^^

) {
if (i == 5) {
>i == 5 : boolean
> : ^^^^^^^
>i : number
> : ^^^^^^
>5 : 5
> : ^

iNext = "bad";
>iNext = "bad" : "bad"
> : ^^^^^
>iNext : any
> : ^^^
>"bad" : "bad"
> : ^^^^^

continue;
}
iNext = i + 1;
>iNext = i + 1 : number
> : ^^^^^^
>iNext : any
> : ^^^
>i + 1 : number
> : ^^^^^^
>i : number
> : ^^^^^^
>1 : 1
> : ^
}
}

{
let iNext: string | number = "";
>iNext : string | number
> : ^^^^^^^^^^^^^^^
>"" : ""
> : ^^

for (
let i = 0;
>i : number
> : ^^^^^^
>0 : 0
> : ^

i < 10;
>i < 10 : boolean
> : ^^^^^^^
>i : number
> : ^^^^^^
>10 : 10
> : ^^

i = iNext // error
>i = iNext : string | number
> : ^^^^^^^^^^^^^^^
>i : number
> : ^^^^^^
>iNext : string | number
> : ^^^^^^^^^^^^^^^

) {
if (i == 5) {
>i == 5 : boolean
> : ^^^^^^^
>i : number
> : ^^^^^^
>5 : 5
> : ^

iNext = "bad";
>iNext = "bad" : "bad"
> : ^^^^^
>iNext : string | number
> : ^^^^^^^^^^^^^^^
>"bad" : "bad"
> : ^^^^^

continue;
}
iNext = i + 1;
>iNext = i + 1 : number
> : ^^^^^^
>iNext : string | number
> : ^^^^^^^^^^^^^^^
>i + 1 : number
> : ^^^^^^
>i : number
> : ^^^^^^
>1 : 1
> : ^
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// @strict: true
// @noEmit: true

// https://github.com/microsoft/TypeScript/issues/60945

{
let iNext;
for (
let i = 0;
i < 10;
i = iNext // error
) {
if (i == 5) {
iNext = "bad";
continue;
}
iNext = i + 1;
}
}

{
let iNext: string | number = "";
for (
let i = 0;
i < 10;
i = iNext // error
) {
if (i == 5) {
iNext = "bad";
continue;
}
iNext = i + 1;
}
}

0 comments on commit 7f802bb

Please sign in to comment.