Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1539,11 +1539,22 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
}

function bindForStatement(node: ForStatement): void {
bind(node.initializer);
if (currentFlow === unreachableFlow) {
// Unlike while/do, the for-loop initializer is bound inside this function before the loop's
// flow graph is constructed. If it makes flow unreachable (e.g. a throwing IIFE), addAntecedent
// will filter out the unreachable entry to preLoopLabel, leaving only the back-edge from the
// incrementor. This creates a cycle with no exit that crashes isReachableFlowNodeWorker.
// Bail out early and just bind the remaining children with unreachable flow.
bind(node.condition);
bind(node.statement);
bind(node.incrementor);
return;
}
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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
unreachableFlowAfterThrowingForHead1.ts(7,9): error TS7027: Unreachable code detected.
unreachableFlowAfterThrowingForHead1.ts(11,2): error TS2304: Cannot find name 'as'.


==== unreachableFlowAfterThrowingForHead1.ts (2 errors) ====
try {
for (
(function () { throw "1"; })();
(function* () { throw "2"; })();
(function* () { throw "3"; })()
) {
console.log("1");
~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
}
}
catch (e) { }
as ;
~~
!!! error TS2304: Cannot find name 'as'.

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

=== unreachableFlowAfterThrowingForHead1.ts ===
try {
for (
(function () { throw "1"; })();
(function* () { throw "2"; })();
(function* () { throw "3"; })()
) {
console.log("1");
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
}
}
catch (e) { }
>e : Symbol(e, Decl(unreachableFlowAfterThrowingForHead1.ts, 9, 7))

as ;

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

=== unreachableFlowAfterThrowingForHead1.ts ===
try {
for (
(function () { throw "1"; })();
>(function () { throw "1"; })() : never
> : ^^^^^
>(function () { throw "1"; }) : () => never
> : ^^^^^^^^^^^
>function () { throw "1"; } : () => never
> : ^^^^^^^^^^^
>"1" : "1"
> : ^^^

(function* () { throw "2"; })();
>(function* () { throw "2"; })() : Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function* () { throw "2"; }) : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function* () { throw "2"; } : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>"2" : "2"
> : ^^^

(function* () { throw "3"; })()
>(function* () { throw "3"; })() : Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function* () { throw "3"; }) : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function* () { throw "3"; } : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>"3" : "3"
> : ^^^

) {
console.log("1");
>console.log("1") : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>"1" : "1"
> : ^^^
}
}
catch (e) { }
>e : unknown
> : ^^^^^^^

as ;
>as : any
> : ^^^

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
unreachableFlowAfterThrowingForHead1.ts(11,2): error TS2304: Cannot find name 'as'.


==== unreachableFlowAfterThrowingForHead1.ts (1 errors) ====
try {
for (
(function () { throw "1"; })();
(function* () { throw "2"; })();
(function* () { throw "3"; })()
) {
console.log("1");
}
}
catch (e) { }
as ;
~~
!!! error TS2304: Cannot find name 'as'.

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

=== unreachableFlowAfterThrowingForHead1.ts ===
try {
for (
(function () { throw "1"; })();
(function* () { throw "2"; })();
(function* () { throw "3"; })()
) {
console.log("1");
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
}
}
catch (e) { }
>e : Symbol(e, Decl(unreachableFlowAfterThrowingForHead1.ts, 9, 7))

as ;

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

=== unreachableFlowAfterThrowingForHead1.ts ===
try {
for (
(function () { throw "1"; })();
>(function () { throw "1"; })() : never
> : ^^^^^
>(function () { throw "1"; }) : () => never
> : ^^^^^^^^^^^
>function () { throw "1"; } : () => never
> : ^^^^^^^^^^^
>"1" : "1"
> : ^^^

(function* () { throw "2"; })();
>(function* () { throw "2"; })() : Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function* () { throw "2"; }) : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function* () { throw "2"; } : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>"2" : "2"
> : ^^^

(function* () { throw "3"; })()
>(function* () { throw "3"; })() : Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function* () { throw "3"; }) : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function* () { throw "3"; } : () => Generator<never, never, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>"3" : "3"
> : ^^^

) {
console.log("1");
>console.log("1") : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>"1" : "1"
> : ^^^
}
}
catch (e) { }
>e : unknown
> : ^^^^^^^

as ;
>as : any
> : ^^^

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
unreachableFlowAfterThrowingForHead2.ts(9,5): error TS7027: Unreachable code detected.
unreachableFlowAfterThrowingForHead2.ts(22,7): error TS7027: Unreachable code detected.


==== unreachableFlowAfterThrowingForHead2.ts (2 errors) ====
function test1(v: 0 | 1 | 2) {
for (
(function () {
throw new Error("");
})();
v;
v++
) {
console.log("1");
~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
}
}

function test2(v: 0 | 1 | 2) {
try {
for (
(function () {
throw new Error("");
})();
v;
v++
) {
console.log("1");
~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
}
} catch (e) {}
v;
}

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

=== unreachableFlowAfterThrowingForHead2.ts ===
function test1(v: 0 | 1 | 2) {
>test1 : Symbol(test1, Decl(unreachableFlowAfterThrowingForHead2.ts, 0, 0))
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 0, 15))

for (
(function () {
throw new Error("");
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --))

})();
v;
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 0, 15))

v++
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 0, 15))

) {
console.log("1");
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
}
}

function test2(v: 0 | 1 | 2) {
>test2 : Symbol(test2, Decl(unreachableFlowAfterThrowingForHead2.ts, 10, 1))
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 12, 15))

try {
for (
(function () {
throw new Error("");
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --))

})();
v;
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 12, 15))

v++
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 12, 15))

) {
console.log("1");
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
}
} catch (e) {}
>e : Symbol(e, Decl(unreachableFlowAfterThrowingForHead2.ts, 23, 11))

v;
>v : Symbol(v, Decl(unreachableFlowAfterThrowingForHead2.ts, 12, 15))
}

Loading