mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-07-01 21:34:46 -05:00
Merge pull request #8421 from Microsoft/controlFlowNestedLoops
Fix control flow analysis in nested loops
This commit is contained in:
@@ -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 :
|
||||
|
||||
39
tests/baselines/reference/controlFlowLoopAnalysis.errors.txt
Normal file
39
tests/baselines/reference/controlFlowLoopAnalysis.errors.txt
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
tests/baselines/reference/controlFlowLoopAnalysis.js
Normal file
58
tests/baselines/reference/controlFlowLoopAnalysis.js
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
tests/cases/compiler/controlFlowLoopAnalysis.ts
Normal file
31
tests/cases/compiler/controlFlowLoopAnalysis.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user