Merge pull request #8421 from Microsoft/controlFlowNestedLoops

Fix control flow analysis in nested loops
This commit is contained in:
Anders Hejlsberg
2016-05-02 12:02:57 -07:00
4 changed files with 140 additions and 11 deletions

View File

@@ -7669,17 +7669,18 @@ namespace ts {
const type = flow.kind === FlowKind.LoopLabel ?
getTypeAtFlowNodeCached(antecedent) :
getTypeAtFlowNode(antecedent);
if (type) {
// If the type at a particular antecedent path is the declared type and the
// reference is known to always be assigned (i.e. when declared and initial types
// are the same), there is no reason to process more antecedents since the only
// possible outcome is subtypes that will be removed in the final union type anyway.
if (type === declaredType && declaredType === initialType) {
return type;
}
if (!contains(antecedentTypes, type)) {
antecedentTypes.push(type);
}
if (!type) {
break;
}
// If the type at a particular antecedent path is the declared type and the
// reference is known to always be assigned (i.e. when declared and initial types
// are the same), there is no reason to process more antecedents since the only
// possible outcome is subtypes that will be removed in the final union type anyway.
if (type === declaredType && declaredType === initialType) {
return type;
}
if (!contains(antecedentTypes, type)) {
antecedentTypes.push(type);
}
}
return antecedentTypes.length === 0 ? undefined :

View File

@@ -0,0 +1,39 @@
tests/cases/compiler/controlFlowLoopAnalysis.ts(13,25): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.
==== tests/cases/compiler/controlFlowLoopAnalysis.ts (1 errors) ====
// Repro from #8418
let cond: boolean;
function foo(x: number): number { return 1; }
function test1() {
let x: number | undefined;
while (cond) {
while (cond) {
while (cond) {
x = foo(x);
~
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
}
}
x = 1;
}
}
// Repro from #8418
function test2() {
let x: number | undefined;
x = 1;
while (cond) {
while (cond) {
x = foo(x);
}
}
}

View File

@@ -0,0 +1,58 @@
//// [controlFlowLoopAnalysis.ts]
// Repro from #8418
let cond: boolean;
function foo(x: number): number { return 1; }
function test1() {
let x: number | undefined;
while (cond) {
while (cond) {
while (cond) {
x = foo(x);
}
}
x = 1;
}
}
// Repro from #8418
function test2() {
let x: number | undefined;
x = 1;
while (cond) {
while (cond) {
x = foo(x);
}
}
}
//// [controlFlowLoopAnalysis.js]
// Repro from #8418
var cond;
function foo(x) { return 1; }
function test1() {
var x;
while (cond) {
while (cond) {
while (cond) {
x = foo(x);
}
}
x = 1;
}
}
// Repro from #8418
function test2() {
var x;
x = 1;
while (cond) {
while (cond) {
x = foo(x);
}
}
}

View File

@@ -0,0 +1,31 @@
// @strictNullChecks: true
// Repro from #8418
let cond: boolean;
function foo(x: number): number { return 1; }
function test1() {
let x: number | undefined;
while (cond) {
while (cond) {
while (cond) {
x = foo(x);
}
}
x = 1;
}
}
// Repro from #8418
function test2() {
let x: number | undefined;
x = 1;
while (cond) {
while (cond) {
x = foo(x);
}
}
}