Fixed an issue with for statement's incrementor missing continue's control flow information (#60950)

This commit is contained in:
Mateusz Burzyński 2025-01-22 20:40:58 +01:00 committed by GitHub
parent b886b48950
commit 7f802bbca2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 277 additions and 1 deletions

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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))
}
}

View File

@ -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
> : ^
}
}

View File

@ -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;
}
}