mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-14 16:56:06 -05:00
Further CFA handling of exhaustive switch statements
This commit is contained in:
@@ -1224,7 +1224,8 @@ namespace ts {
|
||||
addAntecedent(postSwitchLabel, currentFlow);
|
||||
const hasDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause);
|
||||
// We mark a switch statement as possibly exhaustive if it has no default clause and if all
|
||||
// case clauses have unreachable end points (e.g. they all return).
|
||||
// case clauses have unreachable end points (e.g. they all return). Note, we no longer need
|
||||
// this property in control flow analysis, it's there only for backwards compatibility.
|
||||
node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents;
|
||||
if (!hasDefault) {
|
||||
addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0));
|
||||
|
||||
@@ -16999,7 +16999,7 @@ namespace ts {
|
||||
function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck: boolean): boolean {
|
||||
while (true) {
|
||||
const flags = flow.flags;
|
||||
if (flags & FlowFlags.Shared | flags & FlowFlags.SwitchClause) {
|
||||
if (flags & FlowFlags.Shared) {
|
||||
if (!noCacheCheck) {
|
||||
const id = getFlowNodeId(flow);
|
||||
const reachable = flowNodeReachable[id];
|
||||
@@ -17018,12 +17018,16 @@ namespace ts {
|
||||
flow = (<FlowCall>flow).antecedent;
|
||||
}
|
||||
else if (flags & FlowFlags.BranchLabel) {
|
||||
// A branching point is reachable if any branch is reachable.
|
||||
return some((<FlowLabel>flow).antecedents!, isReachableFlowNode);
|
||||
}
|
||||
else if (flags & FlowFlags.LoopLabel) {
|
||||
// A loop is reachable if the control flow path that leads to the top is reachable.
|
||||
flow = (<FlowLabel>flow).antecedents![0];
|
||||
}
|
||||
else if (flags & FlowFlags.SwitchClause) {
|
||||
// The control flow path representing an unmatched value in a switch statement with
|
||||
// no default clause is unreachable if the switch statement is exhaustive.
|
||||
if ((<FlowSwitchClause>flow).clauseStart === (<FlowSwitchClause>flow).clauseEnd && isExhaustiveSwitchStatement((<FlowSwitchClause>flow).switchStatement)) {
|
||||
return false;
|
||||
}
|
||||
@@ -17327,6 +17331,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
|
||||
if (flow.clauseStart === flow.clauseEnd && isExhaustiveSwitchStatement((<FlowSwitchClause>flow).switchStatement)) {
|
||||
return neverType;
|
||||
}
|
||||
const expr = flow.switchStatement.expression;
|
||||
const flowType = getTypeAtFlowNode(flow.antecedent);
|
||||
let type = getTypeFromFlowType(flowType);
|
||||
@@ -23793,9 +23800,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isExhaustiveSwitchStatement(node: SwitchStatement): boolean {
|
||||
if (!node.possiblyExhaustive) {
|
||||
return false;
|
||||
}
|
||||
const links = getNodeLinks(node);
|
||||
return links.isExhaustive !== undefined ? links.isExhaustive : (links.isExhaustive = computeExhaustiveSwitchStatement(node));
|
||||
}
|
||||
|
||||
function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean {
|
||||
if (node.expression.kind === SyntaxKind.TypeOfExpression) {
|
||||
const operandType = getTypeOfExpression((node.expression as TypeOfExpression).expression);
|
||||
// This cast is safe because the switch is possibly exhaustive and does not contain a default case, so there can be no undefined.
|
||||
|
||||
@@ -4016,6 +4016,7 @@ namespace ts {
|
||||
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
|
||||
deferredNodes?: Map<Node>; // Set of nodes whose checking has been deferred
|
||||
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
|
||||
isExhaustive?: boolean; // Is node an exhaustive switch statement
|
||||
}
|
||||
|
||||
export const enum TypeFlags {
|
||||
|
||||
Reference in New Issue
Block a user