Revert to declared type when narrowing produces the nothing type

This commit is contained in:
Anders Hejlsberg
2016-05-10 09:35:23 -07:00
parent 16fccf5d38
commit e944bfab52
2 changed files with 17 additions and 19 deletions
+1 -18
View File
@@ -696,23 +696,6 @@ namespace ts {
};
}
function skipSimpleConditionalFlow(flow: FlowNode) {
// We skip over simple conditional flows of the form 'x ? aaa : bbb', where 'aaa' and 'bbb' contain
// no constructs that affect control flow type analysis. Such simple flows have no effect on the
// code paths that follow and ignoring them means we'll do less work.
if (flow.flags & FlowFlags.BranchLabel && (<FlowLabel>flow).antecedents.length === 2) {
const a = (<FlowLabel>flow).antecedents[0];
const b = (<FlowLabel>flow).antecedents[1];
if ((a.flags & FlowFlags.TrueCondition && b.flags & FlowFlags.FalseCondition ||
a.flags & FlowFlags.FalseCondition && b.flags & FlowFlags.TrueCondition) &&
(<FlowCondition>a).antecedent === (<FlowCondition>b).antecedent &&
(<FlowCondition>a).expression === (<FlowCondition>b).expression) {
return (<FlowCondition>a).antecedent;
}
}
return flow;
}
function finishFlowLabel(flow: FlowLabel): FlowNode {
const antecedents = flow.antecedents;
if (!antecedents) {
@@ -721,7 +704,7 @@ namespace ts {
if (antecedents.length === 1) {
return antecedents[0];
}
return skipSimpleConditionalFlow(flow);
return flow;
}
function isStatementCondition(node: Node) {
+16 -1
View File
@@ -7702,7 +7702,22 @@ namespace ts {
}
function getTypeAtFlowCondition(flow: FlowCondition) {
return narrowType(getTypeAtFlowNode(flow.antecedent), flow.expression, (flow.flags & FlowFlags.TrueCondition) !== 0);
let type = getTypeAtFlowNode(flow.antecedent);
if (type !== emptyUnionType) {
// If we have an antecedent type (meaning we're reachable in some way), we first
// attempt to narrow the antecedent type. If that produces the nothing type, then
// we take the type guard as an indication that control could reach here in a
// manner not understood by the control flow analyzer (e.g. a function argument
// has an invalid type, or a nested function has possibly made an assignment to a
// captured variable). We proceed by reverting to the declared type and then
// narrow that.
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
type = narrowType(type, flow.expression, assumeTrue);
if (type === emptyUnionType) {
type = narrowType(declaredType, flow.expression, assumeTrue);
}
}
return type;
}
function getTypeAtFlowBranchLabel(flow: FlowLabel) {