diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 77ad55a20c9..bb3b7b10508 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -569,7 +569,7 @@ namespace ts { } // We create a return control flow graph for IIFEs and constructors. For constructors // we use the return control flow graph in strict property initialization checks. - currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined; + currentReturnTarget = containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((node).body) ? createBranchLabel() : undefined; currentBreakTarget = undefined; currentContinueTarget = undefined; activeLabels = undefined; @@ -589,9 +589,7 @@ namespace ts { if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); - if (node.kind === SyntaxKind.Constructor) { - (node).returnFlowNode = currentFlow; - } + (node).returnFlowNode = currentFlow; } if (!isIIFE) { currentFlow = saveCurrentFlow; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5630a6ef10..5e491b2e730 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23803,15 +23803,10 @@ namespace ts { return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes); } - function isNeverFunctionCall(expr: Expression) { - const signature = expr.kind === SyntaxKind.CallExpression && getEffectsSignature(expr); - return !!(signature && getReturnTypeOfSignature(signature).flags & TypeFlags.Never); - } - function functionHasImplicitReturn(func: FunctionLikeDeclaration) { - return !!(func.flags & NodeFlags.HasImplicitReturn) && !some((func.body).statements, statement => - statement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(statement) || - statement.kind === SyntaxKind.ExpressionStatement && isNeverFunctionCall((statement).expression)); + return !!(func.flags & NodeFlags.HasImplicitReturn && + !some((func.body).statements, s => s.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(s)) && + !(func.returnFlowNode && !isReachableFlowNode(func.returnFlowNode))); } /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */ diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7486af7148d..214c2d58788 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1040,6 +1040,7 @@ namespace ts { questionToken?: QuestionToken; exclamationToken?: ExclamationToken; body?: Block | Expression; + /* @internal */ returnFlowNode?: FlowNode; } export type FunctionLikeDeclaration = @@ -1085,7 +1086,6 @@ namespace ts { kind: SyntaxKind.Constructor; parent: ClassLikeDeclaration; body?: FunctionBody; - /* @internal */ returnFlowNode?: FlowNode; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */