Skip to content

Commit b88269b

Browse files
committed
Cache control flow types only at loop-back junctions
1 parent 4039146 commit b88269b

File tree

3 files changed

+21
-9
lines changed

3 files changed

+21
-9
lines changed

src/compiler/binder.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,13 @@ namespace ts {
645645
};
646646
}
647647

648+
function createFlowLoopLabel(): FlowLabel {
649+
return {
650+
kind: FlowKind.LoopLabel,
651+
antecedents: undefined
652+
};
653+
}
654+
648655
function addAntecedent(label: FlowLabel, antecedent: FlowNode): void {
649656
if (antecedent.kind !== FlowKind.Unreachable && !contains(label.antecedents, antecedent)) {
650657
(label.antecedents || (label.antecedents = [])).push(antecedent);
@@ -755,7 +762,7 @@ namespace ts {
755762
}
756763

757764
function bindWhileStatement(node: WhileStatement): void {
758-
const preWhileLabel = createFlowLabel();
765+
const preWhileLabel = createFlowLoopLabel();
759766
const preBodyLabel = createFlowLabel();
760767
const postWhileLabel = createFlowLabel();
761768
addAntecedent(preWhileLabel, currentFlow);
@@ -768,7 +775,7 @@ namespace ts {
768775
}
769776

770777
function bindDoStatement(node: DoStatement): void {
771-
const preDoLabel = createFlowLabel();
778+
const preDoLabel = createFlowLoopLabel();
772779
const preConditionLabel = createFlowLabel();
773780
const postDoLabel = createFlowLabel();
774781
addAntecedent(preDoLabel, currentFlow);
@@ -781,7 +788,7 @@ namespace ts {
781788
}
782789

783790
function bindForStatement(node: ForStatement): void {
784-
const preLoopLabel = createFlowLabel();
791+
const preLoopLabel = createFlowLoopLabel();
785792
const preBodyLabel = createFlowLabel();
786793
const postLoopLabel = createFlowLabel();
787794
bind(node.initializer);
@@ -796,7 +803,7 @@ namespace ts {
796803
}
797804

798805
function bindForInOrForOfStatement(node: ForInStatement | ForOfStatement): void {
799-
const preLoopLabel = createFlowLabel();
806+
const preLoopLabel = createFlowLoopLabel();
800807
const postLoopLabel = createFlowLabel();
801808
addAntecedent(preLoopLabel, currentFlow);
802809
currentFlow = preLoopLabel;
@@ -943,7 +950,7 @@ namespace ts {
943950
}
944951

945952
function bindLabeledStatement(node: LabeledStatement): void {
946-
const preStatementLabel = createFlowLabel();
953+
const preStatementLabel = createFlowLoopLabel();
947954
const postStatementLabel = createFlowLabel();
948955
bind(node.label);
949956
addAntecedent(preStatementLabel, currentFlow);

src/compiler/checker.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7592,6 +7592,7 @@ namespace ts {
75927592
case FlowKind.Condition:
75937593
return getTypeAtFlowCondition(<FlowCondition>flow);
75947594
case FlowKind.Label:
7595+
case FlowKind.LoopLabel:
75957596
if ((<FlowLabel>flow).antecedents.length === 1) {
75967597
flow = (<FlowLabel>flow).antecedents[0];
75977598
continue;
@@ -7639,7 +7640,8 @@ namespace ts {
76397640
}
76407641

76417642
function getTypeAtFlowCondition(flow: FlowCondition) {
7642-
return narrowType(getTypeAtFlowNode(flow.antecedent), flow.expression, flow.assumeTrue);
7643+
const type = getTypeAtFlowNode(flow.antecedent);
7644+
return type && narrowType(type, flow.expression, flow.assumeTrue);
76437645
}
76447646

76457647
function getTypeAtFlowNodeCached(flow: FlowNode) {
@@ -7665,13 +7667,15 @@ namespace ts {
76657667
flowStackCount--;
76667668
// Record the result only if the cache is still empty. If checkExpressionCached was called
76677669
// during processing it is possible we've already recorded a result.
7668-
return cache[key] || (cache[key] = type);
7670+
return cache[key] || type && (cache[key] = type);
76697671
}
76707672

76717673
function getTypeAtFlowLabel(flow: FlowLabel) {
76727674
const antecedentTypes: Type[] = [];
76737675
for (const antecedent of flow.antecedents) {
7674-
const type = getTypeAtFlowNodeCached(antecedent);
7676+
const type = flow.kind === FlowKind.LoopLabel ?
7677+
getTypeAtFlowNodeCached(antecedent) :
7678+
getTypeAtFlowNode(antecedent);
76757679
if (type) {
76767680
// If the type at a particular antecedent path is the declared type and the
76777681
// reference is known to always be assigned (i.e. when declared and initial types
@@ -7685,7 +7689,7 @@ namespace ts {
76857689
}
76867690
}
76877691
}
7688-
return antecedentTypes.length === 0 ? declaredType :
7692+
return antecedentTypes.length === 0 ? undefined :
76897693
antecedentTypes.length === 1 ? antecedentTypes[0] :
76907694
getUnionType(antecedentTypes);
76917695
}

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,7 @@ namespace ts {
15191519
Unreachable,
15201520
Start,
15211521
Label,
1522+
LoopLabel,
15221523
Assignment,
15231524
Condition
15241525
}

0 commit comments

Comments
 (0)