Skip to content
Merged
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
12 changes: 11 additions & 1 deletion tsc/internal/binder/binder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1907,9 +1907,19 @@ func (b *Binder) bindForStatement(node *ast.Node) {

func (b *Binder) bindForInOrForOfStatement(node *ast.Node) {
stmt := node.AsForInOrOfStatement()
b.bind(stmt.Expression)
if b.currentFlow == b.unreachableFlow {
// Like the for-loop initializer, the for-in/for-of expression is bound 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
// loop body. This creates a cycle with no exit that crashes isReachableFlowNodeWorker.
// Bail out early and just bind the remaining children with unreachable flow.
b.bind(stmt.Initializer)
b.bind(stmt.Statement)
return
}
preLoopLabel := b.setContinueTarget(node, b.createLoopLabel())
postLoopLabel := b.createBranchLabel()
b.bind(stmt.Expression)
b.addAntecedent(preLoopLabel, b.currentFlow)
b.currentFlow = preLoopLabel
if node.Kind == ast.KindForOfStatement {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
unreachableFlowAfterThrowingForInOfHead1.ts(2,21): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
unreachableFlowAfterThrowingForInOfHead1.ts(3,9): error TS7027: Unreachable code detected.


==== unreachableFlowAfterThrowingForInOfHead1.ts (2 errors) ====
try {
for (const x of (function () { throw "1"; })()) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2773 unreachableFlowAfterThrowingForInOfHead1.ts:2:21: Did you forget to use 'await'?
console.log("1");
~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
}
}
catch (e) { }

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

=== unreachableFlowAfterThrowingForInOfHead1.ts ===
try {
for (const x of (function () { throw "1"; })()) {
>x : Symbol(x, Decl(unreachableFlowAfterThrowingForInOfHead1.ts, 1, 14))

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(unreachableFlowAfterThrowingForInOfHead1.ts, 5, 7))

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

=== unreachableFlowAfterThrowingForInOfHead1.ts ===
try {
for (const x of (function () { throw "1"; })()) {
>x : any
>(function () { throw "1"; })() : never
>(function () { throw "1"; }) : () => never
>function () { throw "1"; } : () => never
>"1" : "1"

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
unreachableFlowAfterThrowingForInOfHead1.ts(2,21): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.


==== unreachableFlowAfterThrowingForInOfHead1.ts (1 errors) ====
try {
for (const x of (function () { throw "1"; })()) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator.
!!! related TS2773 unreachableFlowAfterThrowingForInOfHead1.ts:2:21: Did you forget to use 'await'?
console.log("1");
}
}
catch (e) { }

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

=== unreachableFlowAfterThrowingForInOfHead1.ts ===
try {
for (const x of (function () { throw "1"; })()) {
>x : Symbol(x, Decl(unreachableFlowAfterThrowingForInOfHead1.ts, 1, 14))

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(unreachableFlowAfterThrowingForInOfHead1.ts, 5, 7))

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

=== unreachableFlowAfterThrowingForInOfHead1.ts ===
try {
for (const x of (function () { throw "1"; })()) {
>x : any
>(function () { throw "1"; })() : never
>(function () { throw "1"; }) : () => never
>function () { throw "1"; } : () => never
>"1" : "1"

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
unreachableFlowAfterThrowingForInOfHead2.ts(2,21): error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
unreachableFlowAfterThrowingForInOfHead2.ts(3,9): error TS7027: Unreachable code detected.


==== unreachableFlowAfterThrowingForInOfHead2.ts (2 errors) ====
try {
for (const x in (function () { throw "1"; })()) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
console.log("1");
~~~~~~~~~~~~~~~~~
!!! error TS7027: Unreachable code detected.
}
}
catch (e) { }

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

=== unreachableFlowAfterThrowingForInOfHead2.ts ===
try {
for (const x in (function () { throw "1"; })()) {
>x : Symbol(x, Decl(unreachableFlowAfterThrowingForInOfHead2.ts, 1, 14))

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(unreachableFlowAfterThrowingForInOfHead2.ts, 5, 7))

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

=== unreachableFlowAfterThrowingForInOfHead2.ts ===
try {
for (const x in (function () { throw "1"; })()) {
>x : string
>(function () { throw "1"; })() : never
>(function () { throw "1"; }) : () => never
>function () { throw "1"; } : () => never
>"1" : "1"

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
unreachableFlowAfterThrowingForInOfHead2.ts(2,21): error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.


==== unreachableFlowAfterThrowingForInOfHead2.ts (1 errors) ====
try {
for (const x in (function () { throw "1"; })()) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
console.log("1");
}
}
catch (e) { }

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

=== unreachableFlowAfterThrowingForInOfHead2.ts ===
try {
for (const x in (function () { throw "1"; })()) {
>x : Symbol(x, Decl(unreachableFlowAfterThrowingForInOfHead2.ts, 1, 14))

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(unreachableFlowAfterThrowingForInOfHead2.ts, 5, 7))

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

=== unreachableFlowAfterThrowingForInOfHead2.ts ===
try {
for (const x in (function () { throw "1"; })()) {
>x : string
>(function () { throw "1"; })() : never
>(function () { throw "1"; }) : () => never
>function () { throw "1"; } : () => never
>"1" : "1"

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @strict: true
// @noEmit: true
// @allowUnreachableCode: true, false
// @target: es2015

try {
for (const x of (function () { throw "1"; })()) {
console.log("1");
}
}
catch (e) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @strict: true
// @noEmit: true
// @allowUnreachableCode: true, false
// @target: es2015

try {
for (const x in (function () { throw "1"; })()) {
console.log("1");
}
}
catch (e) { }