@@ -16996,16 +16996,19 @@ namespace ts {
1699616996 return isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ false);
1699716997 }
1699816998
16999- function isReachableFlowNodeWorker(flow: FlowNode, skipCacheCheck : boolean): boolean {
16999+ function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck : boolean): boolean {
1700017000 while (true) {
1700117001 const flags = flow.flags;
17002- if (flags & FlowFlags.Shared && !skipCacheCheck) {
17003- const id = getFlowNodeId(flow);
17004- const reachable = flowNodeReachable[id];
17005- return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ true));
17002+ if (flags & FlowFlags.Shared | flags & FlowFlags.SwitchClause) {
17003+ if (!noCacheCheck) {
17004+ const id = getFlowNodeId(flow);
17005+ const reachable = flowNodeReachable[id];
17006+ return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ true));
17007+ }
17008+ noCacheCheck = false;
1700617009 }
17007- if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.SwitchClause | FlowFlags. ArrayMutation | FlowFlags.PreFinally | FlowFlags.AfterFinally)) {
17008- flow = (<FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation | PreFinallyFlow | AfterFinallyFlow>flow).antecedent;
17010+ if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.PreFinally | FlowFlags.AfterFinally)) {
17011+ flow = (<FlowAssignment | FlowCondition | FlowArrayMutation | PreFinallyFlow | AfterFinallyFlow>flow).antecedent;
1700917012 }
1701017013 else if (flags & FlowFlags.Call) {
1701117014 const signature = getEffectsSignature((<FlowCall>flow).node);
@@ -17014,14 +17017,20 @@ namespace ts {
1701417017 }
1701517018 flow = (<FlowCall>flow).antecedent;
1701617019 }
17020+ else if (flags & FlowFlags.BranchLabel) {
17021+ return some((<FlowLabel>flow).antecedents!, isReachableFlowNode);
17022+ }
1701717023 else if (flags & FlowFlags.LoopLabel) {
1701817024 flow = (<FlowLabel>flow).antecedents![0];
1701917025 }
17020- else if (flags & FlowFlags.BranchLabel) {
17021- return every((<FlowLabel>flow).antecedents!, isReachableFlowNode);
17026+ else if (flags & FlowFlags.SwitchClause) {
17027+ if ((<FlowSwitchClause>flow).clauseStart === (<FlowSwitchClause>flow).clauseEnd && isExhaustiveSwitchStatement((<FlowSwitchClause>flow).switchStatement)) {
17028+ return false;
17029+ }
17030+ flow = (<FlowSwitchClause>flow).antecedent;
1702217031 }
1702317032 else {
17024- return true ;
17033+ return !(flags & FlowFlags.Unreachable) ;
1702517034 }
1702617035 }
1702717036 }
@@ -17044,7 +17053,11 @@ namespace ts {
1704417053 // on empty arrays are possible without implicit any errors and new element types can be inferred without
1704517054 // type mismatch errors.
1704617055 const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType);
17047- if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
17056+ if (resultType === unreachableNeverType) {
17057+ error(reference, Diagnostics.Unreachable_code_detected);
17058+ return declaredType;
17059+ }
17060+ if (reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
1704817061 return declaredType;
1704917062 }
1705017063 return resultType;
@@ -23804,9 +23817,7 @@ namespace ts {
2380423817 }
2380523818
2380623819 function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
23807- return !!(func.flags & NodeFlags.HasImplicitReturn &&
23808- !some((<Block>func.body).statements, s => s.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>s)) &&
23809- !(func.returnFlowNode && !isReachableFlowNode(func.returnFlowNode)));
23820+ return func.endFlowNode && isReachableFlowNode(func.endFlowNode);
2381023821 }
2381123822
2381223823 /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */
0 commit comments