Skip to content

Commit a7e4046

Browse files
committed
Merge pull request microsoft#8421 from Microsoft/controlFlowNestedLoops
Fix control flow analysis in nested loops
2 parents afaffb1 + d9f0293 commit a7e4046

4 files changed

Lines changed: 140 additions & 11 deletions

File tree

src/compiler/checker.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7669,17 +7669,18 @@ namespace ts {
76697669
const type = flow.kind === FlowKind.LoopLabel ?
76707670
getTypeAtFlowNodeCached(antecedent) :
76717671
getTypeAtFlowNode(antecedent);
7672-
if (type) {
7673-
// If the type at a particular antecedent path is the declared type and the
7674-
// reference is known to always be assigned (i.e. when declared and initial types
7675-
// are the same), there is no reason to process more antecedents since the only
7676-
// possible outcome is subtypes that will be removed in the final union type anyway.
7677-
if (type === declaredType && declaredType === initialType) {
7678-
return type;
7679-
}
7680-
if (!contains(antecedentTypes, type)) {
7681-
antecedentTypes.push(type);
7682-
}
7672+
if (!type) {
7673+
break;
7674+
}
7675+
// If the type at a particular antecedent path is the declared type and the
7676+
// reference is known to always be assigned (i.e. when declared and initial types
7677+
// are the same), there is no reason to process more antecedents since the only
7678+
// possible outcome is subtypes that will be removed in the final union type anyway.
7679+
if (type === declaredType && declaredType === initialType) {
7680+
return type;
7681+
}
7682+
if (!contains(antecedentTypes, type)) {
7683+
antecedentTypes.push(type);
76837684
}
76847685
}
76857686
return antecedentTypes.length === 0 ? undefined :
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
tests/cases/compiler/controlFlowLoopAnalysis.ts(13,25): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
2+
Type 'undefined' is not assignable to type 'number'.
3+
4+
5+
==== tests/cases/compiler/controlFlowLoopAnalysis.ts (1 errors) ====
6+
7+
// Repro from #8418
8+
9+
let cond: boolean;
10+
11+
function foo(x: number): number { return 1; }
12+
13+
function test1() {
14+
let x: number | undefined;
15+
while (cond) {
16+
while (cond) {
17+
while (cond) {
18+
x = foo(x);
19+
~
20+
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
21+
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
22+
}
23+
}
24+
x = 1;
25+
}
26+
}
27+
28+
// Repro from #8418
29+
30+
function test2() {
31+
let x: number | undefined;
32+
x = 1;
33+
while (cond) {
34+
while (cond) {
35+
x = foo(x);
36+
}
37+
}
38+
}
39+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//// [controlFlowLoopAnalysis.ts]
2+
3+
// Repro from #8418
4+
5+
let cond: boolean;
6+
7+
function foo(x: number): number { return 1; }
8+
9+
function test1() {
10+
let x: number | undefined;
11+
while (cond) {
12+
while (cond) {
13+
while (cond) {
14+
x = foo(x);
15+
}
16+
}
17+
x = 1;
18+
}
19+
}
20+
21+
// Repro from #8418
22+
23+
function test2() {
24+
let x: number | undefined;
25+
x = 1;
26+
while (cond) {
27+
while (cond) {
28+
x = foo(x);
29+
}
30+
}
31+
}
32+
33+
34+
//// [controlFlowLoopAnalysis.js]
35+
// Repro from #8418
36+
var cond;
37+
function foo(x) { return 1; }
38+
function test1() {
39+
var x;
40+
while (cond) {
41+
while (cond) {
42+
while (cond) {
43+
x = foo(x);
44+
}
45+
}
46+
x = 1;
47+
}
48+
}
49+
// Repro from #8418
50+
function test2() {
51+
var x;
52+
x = 1;
53+
while (cond) {
54+
while (cond) {
55+
x = foo(x);
56+
}
57+
}
58+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// @strictNullChecks: true
2+
3+
// Repro from #8418
4+
5+
let cond: boolean;
6+
7+
function foo(x: number): number { return 1; }
8+
9+
function test1() {
10+
let x: number | undefined;
11+
while (cond) {
12+
while (cond) {
13+
while (cond) {
14+
x = foo(x);
15+
}
16+
}
17+
x = 1;
18+
}
19+
}
20+
21+
// Repro from #8418
22+
23+
function test2() {
24+
let x: number | undefined;
25+
x = 1;
26+
while (cond) {
27+
while (cond) {
28+
x = foo(x);
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)