From 45f30b36a4cc5ce6009da40643e73c1d24f95396 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 13 Nov 2025 17:50:42 -0800 Subject: [PATCH 1/2] Move unreachable checks to checker (#62751) --- src/compiler/binder.ts | 139 ++------------ src/compiler/checker.ts | 98 +++++++++- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 33 +++- .../neverReturningFunctions1.errors.txt | 8 +- .../reference/reachabilityChecks1.errors.txt | 77 +++++++- .../reference/reachabilityChecks10.errors.txt | 11 ++ .../reference/reachabilityChecks10.symbols | 16 ++ .../reference/reachabilityChecks10.types | 35 ++++ .../reference/reachabilityChecks11.errors.txt | 104 ++++++++++ .../reference/reachabilityChecks11.js | 156 +++++++++++++++ .../reference/reachabilityChecks11.symbols | 124 ++++++++++++ .../reference/reachabilityChecks11.types | 180 ++++++++++++++++++ .../reference/reachabilityChecks9.errors.txt | 37 ++++ .../reference/reachabilityChecks9.symbols | 65 +++++++ .../reference/reachabilityChecks9.types | 132 +++++++++++++ .../reference/reachabilityChecksIgnored.js | 28 +++ .../reachabilityChecksIgnored.symbols | 28 +++ .../reference/reachabilityChecksIgnored.types | 54 ++++++ tests/cases/compiler/reachabilityChecks10.ts | 7 + tests/cases/compiler/reachabilityChecks11.ts | 76 ++++++++ tests/cases/compiler/reachabilityChecks9.ts | 29 +++ .../compiler/reachabilityChecksIgnored.ts | 17 ++ ...xUnreachableCode_noSuggestionIfDisabled.ts | 2 +- ...deFixUnusedLabel_noSuggestionIfDisabled.ts | 2 +- 25 files changed, 1305 insertions(+), 154 deletions(-) create mode 100644 tests/baselines/reference/reachabilityChecks10.errors.txt create mode 100644 tests/baselines/reference/reachabilityChecks10.symbols create mode 100644 tests/baselines/reference/reachabilityChecks10.types create mode 100644 tests/baselines/reference/reachabilityChecks11.errors.txt create mode 100644 tests/baselines/reference/reachabilityChecks11.js create mode 100644 tests/baselines/reference/reachabilityChecks11.symbols create mode 100644 tests/baselines/reference/reachabilityChecks11.types create mode 100644 tests/baselines/reference/reachabilityChecks9.errors.txt create mode 100644 tests/baselines/reference/reachabilityChecks9.symbols create mode 100644 tests/baselines/reference/reachabilityChecks9.types create mode 100644 tests/baselines/reference/reachabilityChecksIgnored.js create mode 100644 tests/baselines/reference/reachabilityChecksIgnored.symbols create mode 100644 tests/baselines/reference/reachabilityChecksIgnored.types create mode 100644 tests/cases/compiler/reachabilityChecks10.ts create mode 100644 tests/cases/compiler/reachabilityChecks11.ts create mode 100644 tests/cases/compiler/reachabilityChecks9.ts create mode 100644 tests/cases/compiler/reachabilityChecksIgnored.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 711e7568277c1..e596c72f6db51 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -46,7 +46,6 @@ import { DeleteExpression, DestructuringAssignment, DiagnosticArguments, - DiagnosticCategory, DiagnosticMessage, DiagnosticRelatedInformation, Diagnostics, @@ -87,7 +86,6 @@ import { getAssignmentDeclarationKind, getAssignmentDeclarationPropertyAccessKind, getCombinedModifierFlags, - getCombinedNodeFlags, getContainingClass, getEffectiveContainerForJSDocTemplateTag, getElementOrPropertyAccessName, @@ -105,7 +103,6 @@ import { getNameOfDeclaration, getNameOrArgument, getNodeId, - getRangesWhere, getRightMostAssignedExpression, getSourceFileOfNode, getSourceTextOfNodeFromSourceFile, @@ -114,10 +111,8 @@ import { getSymbolNameForPrivateIdentifier, getTextOfIdentifierOrLiteral, getThisContainer, - getTokenPosOfNode, HasContainerFlags, hasDynamicName, - HasFlowNode, hasJSDocNodes, HasLocals, hasSyntacticModifier, @@ -163,7 +158,6 @@ import { isExternalModule, isExternalOrCommonJsModule, isForInOrOfStatement, - isFunctionDeclaration, isFunctionLike, isFunctionLikeDeclaration, isFunctionLikeOrClassStaticBlockDeclaration, @@ -203,6 +197,7 @@ import { isParenthesizedExpression, isPartOfParameterDeclaration, isPartOfTypeQuery, + isPotentiallyExecutableNode, isPrefixUnaryExpression, isPrivateIdentifier, isPrologueDirective, @@ -216,8 +211,6 @@ import { isSignedNumericLiteral, isSourceFile, isSpecialPropertyDeclaration, - isStatement, - isStatementButNotDeclaration, isStatic, isString, isStringLiteralLike, @@ -284,10 +277,8 @@ import { setParentRecursive, setValueDeclaration, ShorthandPropertyAssignment, - shouldPreserveConstEnums, SignatureDeclaration, skipParentheses, - sliceAfter, some, SourceFile, SpreadElement, @@ -300,7 +291,6 @@ import { symbolName, SymbolTable, SyntaxKind, - TextRange, ThisExpression, ThrowStatement, tokenToString, @@ -313,8 +303,6 @@ import { TypeOfExpression, TypeParameterDeclaration, unescapeLeadingUnderscores, - unreachableCodeIsError, - unusedLabelIsError, VariableDeclaration, WhileStatement, WithStatement, @@ -562,7 +550,6 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { var classifiableNames: Set<__String>; var unreachableFlow = createFlowNode(FlowFlags.Unreachable, /*node*/ undefined, /*antecedent*/ undefined); - var reportedUnreachableFlow = createFlowNode(FlowFlags.Unreachable, /*node*/ undefined, /*antecedent*/ undefined); var bindBinaryExpressionFlow = createBindBinaryExpressionFlow(); /* eslint-enable no-var */ @@ -588,7 +575,6 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // Attach debugging information if necessary Debug.attachFlowNodeDebugInfo(unreachableFlow); - Debug.attachFlowNodeDebugInfo(reportedUnreachableFlow); if (!file.locals) { tracing?.push(tracing.Phase.Bind, "bindSourceFile", { path: file.path }, /*separateBeginAndEnd*/ true); @@ -1099,18 +1085,24 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // Most nodes aren't valid in an assignment pattern, so we clear the value here // and set it before we descend into nodes that could actually be part of an assignment pattern. inAssignmentPattern = false; - if (checkUnreachable(node)) { - if (canHaveFlowNode(node) && node.flowNode) { + + if (currentFlow === unreachableFlow) { + if (canHaveFlowNode(node)) { node.flowNode = undefined; } + if (isPotentiallyExecutableNode(node)) { + (node as Mutable).flags |= NodeFlags.Unreachable; + } bindEachChild(node); bindJSDoc(node); inAssignmentPattern = saveInAssignmentPattern; return; } - if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement && (!options.allowUnreachableCode || node.kind === SyntaxKind.ReturnStatement)) { - (node as HasFlowNode).flowNode = currentFlow; + + if (SyntaxKind.FirstStatement <= node.kind && node.kind <= SyntaxKind.LastStatement && canHaveFlowNode(node)) { + node.flowNode = currentFlow; } + switch (node.kind) { case SyntaxKind.WhileStatement: bindWhileStatement(node as WhileStatement); @@ -1788,8 +1780,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { }; bind(node.label); bind(node.statement); - if (!activeLabelList.referenced && !options.allowUnusedLabels) { - errorOrSuggestionOnNode(unusedLabelIsError(options), node.label, Diagnostics.Unused_label); + if (!activeLabelList.referenced) { + (node.label as Mutable).flags |= NodeFlags.Unreachable; } activeLabelList = activeLabelList.next; addAntecedent(postStatementLabel, currentFlow); @@ -2708,24 +2700,6 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, ...args)); } - function errorOrSuggestionOnNode(isError: boolean, node: Node, message: DiagnosticMessage): void { - errorOrSuggestionOnRange(isError, node, node, message); - } - - function errorOrSuggestionOnRange(isError: boolean, startNode: Node, endNode: Node, message: DiagnosticMessage): void { - addErrorOrSuggestionDiagnostic(isError, { pos: getTokenPosOfNode(startNode, file), end: endNode.end }, message); - } - - function addErrorOrSuggestionDiagnostic(isError: boolean, range: TextRange, message: DiagnosticMessage): void { - const diag = createFileDiagnostic(file, range.pos, range.end - range.pos, message); - if (isError) { - file.bindDiagnostics.push(diag); - } - else { - file.bindSuggestionDiagnostics = append(file.bindSuggestionDiagnostics, { ...diag, category: DiagnosticCategory.Suggestion }); - } - } - function bind(node: Node | undefined): void { if (!node) { return; @@ -3757,93 +3731,6 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } } - - // reachability checks - - function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean { - const instanceState = getModuleInstanceState(node); - return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && shouldPreserveConstEnums(options)); - } - - function checkUnreachable(node: Node): boolean { - if (!(currentFlow.flags & FlowFlags.Unreachable)) { - return false; - } - if (currentFlow === unreachableFlow) { - const reportError = - // report error on all statements except empty ones - (isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) || - // report error on class declarations - node.kind === SyntaxKind.ClassDeclaration || - // report errors on enums with preserved emit - isEnumDeclarationWithPreservedEmit(node, options) || - // report error on instantiated modules - (node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(node as ModuleDeclaration)); - - if (reportError) { - currentFlow = reportedUnreachableFlow; - - if (!options.allowUnreachableCode) { - // unreachable code is reported if - // - user has explicitly asked about it AND - // - statement is in not ambient context (statements in ambient context is already an error - // so we should not report extras) AND - // - node is not variable statement OR - // - node is block scoped variable statement OR - // - node is not block scoped variable statement and at least one variable declaration has initializer - // Rationale: we don't want to report errors on non-initialized var's since they are hoisted - // On the other side we do want to report errors on non-initialized 'lets' because of TDZ - const isError = unreachableCodeIsError(options) && - !(node.flags & NodeFlags.Ambient) && - ( - !isVariableStatement(node) || - !!(getCombinedNodeFlags(node.declarationList) & NodeFlags.BlockScoped) || - node.declarationList.declarations.some(d => !!d.initializer) - ); - - eachUnreachableRange(node, options, (start, end) => errorOrSuggestionOnRange(isError, start, end, Diagnostics.Unreachable_code_detected)); - } - } - } - return true; - } -} - -function isEnumDeclarationWithPreservedEmit(node: Node, options: CompilerOptions): boolean { - return node.kind === SyntaxKind.EnumDeclaration && (!isEnumConst(node as EnumDeclaration) || shouldPreserveConstEnums(options)); -} - -function eachUnreachableRange(node: Node, options: CompilerOptions, cb: (start: Node, last: Node) => void): void { - if (isStatement(node) && isExecutableStatement(node) && isBlock(node.parent)) { - const { statements } = node.parent; - const slice = sliceAfter(statements, node); - getRangesWhere(slice, isExecutableStatement, (start, afterEnd) => cb(slice[start], slice[afterEnd - 1])); - } - else { - cb(node, node); - } - - // As opposed to a pure declaration like an `interface` - function isExecutableStatement(s: Statement): boolean { - // Don't remove statements that can validly be used before they appear. - return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && - // `var x;` may declare a variable used above - !(isVariableStatement(s) && !(getCombinedNodeFlags(s) & (NodeFlags.BlockScoped)) && s.declarationList.declarations.some(d => !d.initializer)); - } - - function isPurelyTypeDeclaration(s: Statement): boolean { - switch (s.kind) { - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - return true; - case SyntaxKind.ModuleDeclaration: - return getModuleInstanceState(s as ModuleDeclaration) !== ModuleInstanceState.Instantiated; - case SyntaxKind.EnumDeclaration: - return !isEnumDeclarationWithPreservedEmit(s, options); - default: - return false; - } - } } /** @internal */ diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cc93702c8a4e5..f8662b7b854a2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -62,6 +62,7 @@ import { canHaveLocals, canHaveModifiers, canHaveModuleSpecifier, + canHaveStatements, canHaveSymbol, canIncludeBindAndCheckDiagnostics, canUsePropertyAccess, @@ -707,6 +708,7 @@ import { isPartOfTypeOnlyImportOrExportDeclaration, isPartOfTypeQuery, isPlainJsFile, + isPotentiallyExecutableNode, isPrefixUnaryExpression, isPrivateIdentifier, isPrivateIdentifierClassElementDeclaration, @@ -1513,6 +1515,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var currentNode: Node | undefined; var varianceTypeParameter: TypeParameter | undefined; var isInferencePartiallyBlocked = false; + var withinUnreachableCode = false; + var reportedUnreachableNodes: Set | undefined; var emptySymbols = createSymbolTable(); var arrayVariances = [VarianceFlags.Covariant]; @@ -46299,6 +46303,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); } + if (node.label.flags & NodeFlags.Unreachable && compilerOptions.allowUnusedLabels !== true) { + errorOrSuggestion(compilerOptions.allowUnusedLabels === false, node.label, Diagnostics.Unused_label); + } + // ensure that label is unique checkSourceElement(node.statement); } @@ -48660,10 +48668,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkSourceElement(node: Node | undefined): void { if (node) { const saveCurrentNode = currentNode; + const saveWithinUnreachableCode = withinUnreachableCode; currentNode = node; instantiationCount = 0; checkSourceElementWorker(node); currentNode = saveCurrentNode; + withinUnreachableCode = saveWithinUnreachableCode; } } @@ -48696,8 +48706,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { cancellationToken.throwIfCancellationRequested(); } } - if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && canHaveFlowNode(node) && node.flowNode && !isReachableFlowNode(node.flowNode)) { - errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, Diagnostics.Unreachable_code_detected); + + if (compilerOptions.allowUnreachableCode !== true && !withinUnreachableCode) { + if (checkSourceElementUnreachable(node)) { + withinUnreachableCode = true; + } } // If editing this, keep `isSourceElement` in utilities up to date. @@ -48878,6 +48891,86 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } + function checkSourceElementUnreachable(node: Node): boolean { + if (!isPotentiallyExecutableNode(node)) { + return false; + } + + if (reportedUnreachableNodes?.has(node)) { + return true; + } + + if (!isSourceElementUnreachable(node)) { + return false; + } + + (reportedUnreachableNodes ??= new Set()).add(node); + + const sourceFile = getSourceFileOfNode(node); + + let start = node.pos; + let end = node.end; + + const parent = node.parent; + if (canHaveStatements(parent)) { + const statements = parent.statements; + const offset = statements.indexOf(node as Statement); + if (offset >= 0) { + // Scan backwards to find the first unreachable unreported node; + // this may happen when producing region diagnostics where not all nodes + // will have been visited. + let first = offset; + for (let i = offset - 1; i >= 0; i--) { + const prevNode = statements[i]; + if (!isPotentiallyExecutableNode(prevNode) || reportedUnreachableNodes.has(prevNode) || !isSourceElementUnreachable(prevNode)) { + break; + } + first = i; + reportedUnreachableNodes.add(prevNode); + } + + let last = offset; + for (let i = offset + 1; i < statements.length; i++) { + const nextNode = statements[i]; + if (!isPotentiallyExecutableNode(nextNode) || !isSourceElementUnreachable(nextNode)) { + break; + } + last = i; + reportedUnreachableNodes.add(nextNode); + } + + start = statements[first].pos; + end = statements[last].end; + } + } + + start = skipTrivia(sourceFile.text, start); + addErrorOrSuggestion(compilerOptions.allowUnreachableCode === false, createFileDiagnostic(sourceFile, start, end - start, Diagnostics.Unreachable_code_detected)); + + return true; + } + + function isSourceElementUnreachable(node: Node): boolean { + // Precondition: isPotentiallyExecutableNode is true + if (node.flags & NodeFlags.Unreachable) { + // The binder has determined that this code is unreachable. + // Ignore const enums unless preserveConstEnums is set. + switch (node.kind) { + case SyntaxKind.EnumDeclaration: + return !isEnumConst(node as EnumDeclaration) || shouldPreserveConstEnums(compilerOptions); + case SyntaxKind.ModuleDeclaration: + return isInstantiatedModule(node as ModuleDeclaration, shouldPreserveConstEnums(compilerOptions)); + default: + return true; + } + } + else if (canHaveFlowNode(node) && node.flowNode) { + // For code the binder doesn't know is unreachable, use control flow / types. + return !isReachableFlowNode(node.flowNode); + } + return false; + } + function checkJSDocCommentWorker(node: string | readonly JSDocComment[] | undefined) { if (isArray(node)) { forEach(node, tag => { @@ -49076,6 +49169,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { performance.mark(afterMark); performance.measure("Check", beforeMark, afterMark); tracing?.pop(); + reportedUnreachableNodes = undefined; } function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 08cf2a4a27e86..4c42fd2281ac5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -823,6 +823,7 @@ export const enum NodeFlags { JsonFile = 1 << 27, // If node was parsed in a Json /** @internal */ TypeCached = 1 << 28, // If a type was cached for node at any point /** @internal */ Deprecated = 1 << 29, // If has '@deprecated' JSDoc tag + /** @internal */ Unreachable = 1 << 30, // If node is unreachable according to the binder BlockScoped = Let | Const | Using, Constant = Const | Using, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e0cb3fa1758d3..d53d15f3c6e59 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -261,7 +261,9 @@ import { isBinaryExpression, isBindingElement, isBindingPattern, + isBlock, isCallExpression, + isCaseClause, isClassDeclaration, isClassElement, isClassExpression, @@ -274,6 +276,7 @@ import { isDeclaration, isDeclarationFileName, isDecorator, + isDefaultClause, isElementAccessExpression, isEnumDeclaration, isEnumMember, @@ -332,6 +335,7 @@ import { isMethodDeclaration, isMethodOrAccessor, isModifierLike, + isModuleBlock, isModuleDeclaration, isModuleOrEnumDeclaration, isNamedDeclaration, @@ -9244,16 +9248,6 @@ export function hasJsonModuleEmitEnabled(options: CompilerOptions): boolean { return true; } -/** @internal */ -export function unreachableCodeIsError(options: CompilerOptions): boolean { - return options.allowUnreachableCode === false; -} - -/** @internal */ -export function unusedLabelIsError(options: CompilerOptions): boolean { - return options.allowUnusedLabels === false; -} - /** @internal */ export function moduleResolutionSupportsPackageJsonExportsAndImports(moduleResolution: ModuleResolutionKind): boolean { return moduleResolution >= ModuleResolutionKind.Node16 && moduleResolution <= ModuleResolutionKind.NodeNext @@ -12323,3 +12317,22 @@ function addEmitFlagsRecursively(node: Node, flag: EmitFlags, getChild: (n: Node function getFirstChild(node: Node): Node | undefined { return forEachChild(node, child => child); } + +/** @internal */ +export function canHaveStatements(node: Node): node is Block | ModuleBlock | SourceFile | CaseClause | DefaultClause { + return isBlock(node) || isModuleBlock(node) || isSourceFile(node) || isCaseClause(node) || isDefaultClause(node); +} + +/** @internal */ +export function isPotentiallyExecutableNode(node: Node): boolean { + if (SyntaxKind.FirstStatement <= node.kind && node.kind <= SyntaxKind.LastStatement) { + if (isVariableStatement(node)) { + if (getCombinedNodeFlags(node.declarationList) & NodeFlags.BlockScoped) { + return true; + } + return some(node.declarationList.declarations, d => d.initializer !== undefined); + } + return true; + } + return isClassDeclaration(node) || isEnumDeclaration(node) || isModuleDeclaration(node); +} diff --git a/tests/baselines/reference/neverReturningFunctions1.errors.txt b/tests/baselines/reference/neverReturningFunctions1.errors.txt index 8a7a8837147b9..a15d15e17dbba 100644 --- a/tests/baselines/reference/neverReturningFunctions1.errors.txt +++ b/tests/baselines/reference/neverReturningFunctions1.errors.txt @@ -13,7 +13,6 @@ neverReturningFunctions1.ts(101,13): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(103,9): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(105,5): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(111,9): error TS7027: Unreachable code detected. -neverReturningFunctions1.ts(112,9): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(122,9): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(127,9): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(129,5): error TS7027: Unreachable code detected. @@ -23,7 +22,7 @@ neverReturningFunctions1.ts(148,9): error TS7027: Unreachable code detected. neverReturningFunctions1.ts(153,5): error TS7027: Unreachable code detected. -==== neverReturningFunctions1.ts (23 errors) ==== +==== neverReturningFunctions1.ts (22 errors) ==== function fail(message?: string): never { throw new Error(message); } @@ -163,10 +162,9 @@ neverReturningFunctions1.ts(153,5): error TS7027: Unreachable code detected. if (typeof x.a === "string") { fail(); x; // Unreachable - ~~ -!!! error TS7027: Unreachable code detected. + ~~~~~~~~~~~~~~~~~~~~ x.a; // Unreachable - ~~~~ + ~~~~~~~~~~~~ !!! error TS7027: Unreachable code detected. } x; // { a: string | number } diff --git a/tests/baselines/reference/reachabilityChecks1.errors.txt b/tests/baselines/reference/reachabilityChecks1.errors.txt index d25977a05b774..accc1d8fa7202 100644 --- a/tests/baselines/reference/reachabilityChecks1.errors.txt +++ b/tests/baselines/reference/reachabilityChecks1.errors.txt @@ -1,58 +1,105 @@ reachabilityChecks1.ts(2,1): error TS7027: Unreachable code detected. -reachabilityChecks1.ts(6,5): error TS7027: Unreachable code detected. -reachabilityChecks1.ts(18,5): error TS7027: Unreachable code detected. -reachabilityChecks1.ts(30,5): error TS7027: Unreachable code detected. reachabilityChecks1.ts(47,5): error TS7027: Unreachable code detected. +reachabilityChecks1.ts(51,1): error TS7027: Unreachable code detected. reachabilityChecks1.ts(60,5): error TS7027: Unreachable code detected. reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. -==== reachabilityChecks1.ts (7 errors) ==== +==== reachabilityChecks1.ts (5 errors) ==== while (true); var x = 1; ~~~~~~~~~~ -!!! error TS7027: Unreachable code detected. + +<<<<<<< HEAD module A { +======= + namespace A { + ~~~~~~~~~~~~~ +>>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) while (true); + ~~~~~~~~~~~~~~~~~ let x; - ~~~~~~ -!!! error TS7027: Unreachable code detected. + ~~~~~~~~~~ } + ~ + +<<<<<<< HEAD module A1 { do {} while(true); module A { +======= + namespace A1 { + ~~~~~~~~~~~~~~ + do {} while(true); + ~~~~~~~~~~~~~~~~~~~~~~ + namespace A { + ~~~~~~~~~~~~~~~~~ +>>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) interface F {} + ~~~~~~~~~~~~~~~~~~~~~~ } + ~~~~~ } + ~ + +<<<<<<< HEAD module A2 { while (true); module A { ~~~~~~~~~~ +======= + namespace A2 { + ~~~~~~~~~~~~~~ + while (true); + ~~~~~~~~~~~~~~~~~ + namespace A { + ~~~~~~~~~~~~~~~~~ +>>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) var x = 1; ~~~~~~~~~~~~~~~~~~ } ~~~~~ -!!! error TS7027: Unreachable code detected. } + ~ + +<<<<<<< HEAD module A3 { +======= + namespace A3 { + ~~~~~~~~~~~~~~ +>>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) while (true); + ~~~~~~~~~~~~~~~~~ type T = string; + ~~~~~~~~~~~~~~~~~~~~ } + ~ + +<<<<<<< HEAD module A4 { while (true); module A { ~~~~~~~~~~ +======= + namespace A4 { + ~~~~~~~~~~~~~~ + while (true); + ~~~~~~~~~~~~~~~~~ + namespace A { + ~~~~~~~~~~~~~~~~~ +>>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) const enum E { X } ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~~~~~ -!!! error TS7027: Unreachable code detected. } + ~ +!!! error TS7027: Unreachable code detected. function f1(x) { if (x) { @@ -73,11 +120,23 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. !!! error TS7027: Unreachable code detected. } +<<<<<<< HEAD module B { for (; ;); module C { +======= + namespace B { + ~~~~~~~~~~~~~ + for (; ;); + ~~~~~~~~~~~~~~ + namespace C { + ~~~~~~~~~~~~~~~~~ +>>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) } + ~~~~~ } + ~ +!!! error TS7027: Unreachable code detected. function f3() { do { diff --git a/tests/baselines/reference/reachabilityChecks10.errors.txt b/tests/baselines/reference/reachabilityChecks10.errors.txt new file mode 100644 index 0000000000000..2b26eae20f99e --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks10.errors.txt @@ -0,0 +1,11 @@ +reachabilityChecks10.ts(2,1): error TS7027: Unreachable code detected. + + +==== reachabilityChecks10.ts (1 errors) ==== + throw new Error("") + console.log("1") + ~~~~~~~~~~~~~~~~ + console.log("2") + ~~~~~~~~~~~~~~~~ +!!! error TS7027: Unreachable code detected. + \ No newline at end of file diff --git a/tests/baselines/reference/reachabilityChecks10.symbols b/tests/baselines/reference/reachabilityChecks10.symbols new file mode 100644 index 0000000000000..6ecc554153996 --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks10.symbols @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/reachabilityChecks10.ts] //// + +=== reachabilityChecks10.ts === +throw new Error("") +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +console.log("1") +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + +console.log("2") +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + diff --git a/tests/baselines/reference/reachabilityChecks10.types b/tests/baselines/reference/reachabilityChecks10.types new file mode 100644 index 0000000000000..bfe7b1bfefe8d --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks10.types @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/reachabilityChecks10.ts] //// + +=== reachabilityChecks10.ts === +throw new Error("") +>new Error("") : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ +>"" : "" +> : ^^ + +console.log("1") +>console.log("1") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"1" : "1" +> : ^^^ + +console.log("2") +>console.log("2") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"2" : "2" +> : ^^^ + diff --git a/tests/baselines/reference/reachabilityChecks11.errors.txt b/tests/baselines/reference/reachabilityChecks11.errors.txt new file mode 100644 index 0000000000000..b4497ee46432a --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks11.errors.txt @@ -0,0 +1,104 @@ +reachabilityChecks11.ts(6,5): error TS7027: Unreachable code detected. +reachabilityChecks11.ts(18,5): error TS7027: Unreachable code detected. +reachabilityChecks11.ts(30,5): error TS7027: Unreachable code detected. +reachabilityChecks11.ts(47,5): error TS7027: Unreachable code detected. +reachabilityChecks11.ts(60,5): error TS7027: Unreachable code detected. +reachabilityChecks11.ts(69,5): error TS7027: Unreachable code detected. + + +==== reachabilityChecks11.ts (6 errors) ==== + // while (true); + var x = 1; + + module A { + while (true); + let x; + ~~~~~~ +!!! error TS7027: Unreachable code detected. + } + + module A1 { + do {} while(true); + module A { + interface F {} + } + } + + module A2 { + while (true); + module A { + ~~~~~~~~~~ + var x = 1; + ~~~~~~~~~~~~~~~~~~ + } + ~~~~~ +!!! error TS7027: Unreachable code detected. + } + + module A3 { + while (true); + type T = string; + } + + module A4 { + while (true); + module A { + ~~~~~~~~~~ + const enum E { X } + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + ~~~~~ +!!! error TS7027: Unreachable code detected. + } + + function f1(x) { + if (x) { + return; + } + else { + throw new Error("123"); + } + var x; + } + + function f2() { + return; + class A { + ~~~~~~~~~ + } + ~~~~~ +!!! error TS7027: Unreachable code detected. + } + + module B { + for (; ;); + module C { + } + } + + function f3() { + do { + } while (true); + enum E { + ~~~~~~~~ + X = 1 + ~~~~~~~~~~~~~ + } + ~~~~~ +!!! error TS7027: Unreachable code detected. + } + + function f4() { + if (true) { + throw new Error(); + } + const enum E { + ~~~~~~~~~~~~~~ + X = 1 + ~~~~~~~~~~~~~ + } + ~~~~~ +!!! error TS7027: Unreachable code detected. + } + + \ No newline at end of file diff --git a/tests/baselines/reference/reachabilityChecks11.js b/tests/baselines/reference/reachabilityChecks11.js new file mode 100644 index 0000000000000..d115e58e816cb --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks11.js @@ -0,0 +1,156 @@ +//// [tests/cases/compiler/reachabilityChecks11.ts] //// + +//// [reachabilityChecks11.ts] +// while (true); +var x = 1; + +module A { + while (true); + let x; +} + +module A1 { + do {} while(true); + module A { + interface F {} + } +} + +module A2 { + while (true); + module A { + var x = 1; + } +} + +module A3 { + while (true); + type T = string; +} + +module A4 { + while (true); + module A { + const enum E { X } + } +} + +function f1(x) { + if (x) { + return; + } + else { + throw new Error("123"); + } + var x; +} + +function f2() { + return; + class A { + } +} + +module B { + for (; ;); + module C { + } +} + +function f3() { + do { + } while (true); + enum E { + X = 1 + } +} + +function f4() { + if (true) { + throw new Error(); + } + const enum E { + X = 1 + } +} + + + +//// [reachabilityChecks11.js] +// while (true); +var x = 1; +var A; +(function (A) { + while (true) + ; + var x; +})(A || (A = {})); +var A1; +(function (A1) { + do { } while (true); +})(A1 || (A1 = {})); +var A2; +(function (A2) { + while (true) + ; + var A; + (function (A) { + var x = 1; + })(A || (A = {})); +})(A2 || (A2 = {})); +var A3; +(function (A3) { + while (true) + ; +})(A3 || (A3 = {})); +var A4; +(function (A4) { + while (true) + ; + var A; + (function (A) { + var E; + (function (E) { + E[E["X"] = 0] = "X"; + })(E || (E = {})); + })(A || (A = {})); +})(A4 || (A4 = {})); +function f1(x) { + if (x) { + return; + } + else { + throw new Error("123"); + } + var x; +} +function f2() { + return; + var A = /** @class */ (function () { + function A() { + } + return A; + }()); +} +var B; +(function (B) { + for (;;) + ; +})(B || (B = {})); +function f3() { + do { + } while (true); + var E; + (function (E) { + E[E["X"] = 1] = "X"; + })(E || (E = {})); +} +function f4() { + if (true) { + throw new Error(); + } + var E; + (function (E) { + E[E["X"] = 1] = "X"; + })(E || (E = {})); +} diff --git a/tests/baselines/reference/reachabilityChecks11.symbols b/tests/baselines/reference/reachabilityChecks11.symbols new file mode 100644 index 0000000000000..450ccad803ff5 --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks11.symbols @@ -0,0 +1,124 @@ +//// [tests/cases/compiler/reachabilityChecks11.ts] //// + +=== reachabilityChecks11.ts === +// while (true); +var x = 1; +>x : Symbol(x, Decl(reachabilityChecks11.ts, 1, 3)) + +module A { +>A : Symbol(A, Decl(reachabilityChecks11.ts, 1, 10)) + + while (true); + let x; +>x : Symbol(x, Decl(reachabilityChecks11.ts, 5, 7)) +} + +module A1 { +>A1 : Symbol(A1, Decl(reachabilityChecks11.ts, 6, 1)) + + do {} while(true); + module A { +>A : Symbol(A, Decl(reachabilityChecks11.ts, 9, 22)) + + interface F {} +>F : Symbol(F, Decl(reachabilityChecks11.ts, 10, 14)) + } +} + +module A2 { +>A2 : Symbol(A2, Decl(reachabilityChecks11.ts, 13, 1)) + + while (true); + module A { +>A : Symbol(A, Decl(reachabilityChecks11.ts, 16, 17)) + + var x = 1; +>x : Symbol(x, Decl(reachabilityChecks11.ts, 18, 11)) + } +} + +module A3 { +>A3 : Symbol(A3, Decl(reachabilityChecks11.ts, 20, 1)) + + while (true); + type T = string; +>T : Symbol(T, Decl(reachabilityChecks11.ts, 23, 17)) +} + +module A4 { +>A4 : Symbol(A4, Decl(reachabilityChecks11.ts, 25, 1)) + + while (true); + module A { +>A : Symbol(A, Decl(reachabilityChecks11.ts, 28, 17)) + + const enum E { X } +>E : Symbol(E, Decl(reachabilityChecks11.ts, 29, 14)) +>X : Symbol(E.X, Decl(reachabilityChecks11.ts, 30, 22)) + } +} + +function f1(x) { +>f1 : Symbol(f1, Decl(reachabilityChecks11.ts, 32, 1)) +>x : Symbol(x, Decl(reachabilityChecks11.ts, 34, 12), Decl(reachabilityChecks11.ts, 41, 7)) + + if (x) { +>x : Symbol(x, Decl(reachabilityChecks11.ts, 34, 12), Decl(reachabilityChecks11.ts, 41, 7)) + + return; + } + else { + throw new Error("123"); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + } + var x; +>x : Symbol(x, Decl(reachabilityChecks11.ts, 34, 12), Decl(reachabilityChecks11.ts, 41, 7)) +} + +function f2() { +>f2 : Symbol(f2, Decl(reachabilityChecks11.ts, 42, 1)) + + return; + class A { +>A : Symbol(A, Decl(reachabilityChecks11.ts, 45, 11)) + } +} + +module B { +>B : Symbol(B, Decl(reachabilityChecks11.ts, 48, 1)) + + for (; ;); + module C { +>C : Symbol(C, Decl(reachabilityChecks11.ts, 51, 14)) + } +} + +function f3() { +>f3 : Symbol(f3, Decl(reachabilityChecks11.ts, 54, 1)) + + do { + } while (true); + enum E { +>E : Symbol(E, Decl(reachabilityChecks11.ts, 58, 19)) + + X = 1 +>X : Symbol(E.X, Decl(reachabilityChecks11.ts, 59, 12)) + } +} + +function f4() { +>f4 : Symbol(f4, Decl(reachabilityChecks11.ts, 62, 1)) + + if (true) { + throw new Error(); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + } + const enum E { +>E : Symbol(E, Decl(reachabilityChecks11.ts, 67, 5)) + + X = 1 +>X : Symbol(E.X, Decl(reachabilityChecks11.ts, 68, 18)) + } +} + + diff --git a/tests/baselines/reference/reachabilityChecks11.types b/tests/baselines/reference/reachabilityChecks11.types new file mode 100644 index 0000000000000..49fcc60359573 --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks11.types @@ -0,0 +1,180 @@ +//// [tests/cases/compiler/reachabilityChecks11.ts] //// + +=== reachabilityChecks11.ts === +// while (true); +var x = 1; +>x : number +> : ^^^^^^ +>1 : 1 +> : ^ + +module A { +>A : typeof A +> : ^^^^^^^^ + + while (true); +>true : true +> : ^^^^ + + let x; +>x : any +> : ^^^ +} + +module A1 { +>A1 : typeof A1 +> : ^^^^^^^^^ + + do {} while(true); +>true : true +> : ^^^^ + + module A { + interface F {} + } +} + +module A2 { +>A2 : typeof A2 +> : ^^^^^^^^^ + + while (true); +>true : true +> : ^^^^ + + module A { +>A : typeof A +> : ^^^^^^^^ + + var x = 1; +>x : number +> : ^^^^^^ +>1 : 1 +> : ^ + } +} + +module A3 { +>A3 : typeof A3 +> : ^^^^^^^^^ + + while (true); +>true : true +> : ^^^^ + + type T = string; +>T : string +> : ^^^^^^ +} + +module A4 { +>A4 : typeof A4 +> : ^^^^^^^^^ + + while (true); +>true : true +> : ^^^^ + + module A { + const enum E { X } +>E : E +> : ^ +>X : E.X +> : ^^^ + } +} + +function f1(x) { +>f1 : (x: any) => void +> : ^ ^^^^^^^^^^^^^^ +>x : any +> : ^^^ + + if (x) { +>x : any +> : ^^^ + + return; + } + else { + throw new Error("123"); +>new Error("123") : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ +>"123" : "123" +> : ^^^^^ + } + var x; +>x : any +> : ^^^ +} + +function f2() { +>f2 : () => void +> : ^^^^^^^^^^ + + return; + class A { +>A : A +> : ^ + } +} + +module B { +>B : typeof B +> : ^^^^^^^^ + + for (; ;); + module C { + } +} + +function f3() { +>f3 : () => void +> : ^^^^^^^^^^ + + do { + } while (true); +>true : true +> : ^^^^ + + enum E { +>E : E +> : ^ + + X = 1 +>X : E.X +> : ^^^ +>1 : 1 +> : ^ + } +} + +function f4() { +>f4 : () => void +> : ^^^^^^^^^^ + + if (true) { +>true : true +> : ^^^^ + + throw new Error(); +>new Error() : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ + } + const enum E { +>E : E +> : ^ + + X = 1 +>X : E.X +> : ^^^ +>1 : 1 +> : ^ + } +} + + diff --git a/tests/baselines/reference/reachabilityChecks9.errors.txt b/tests/baselines/reference/reachabilityChecks9.errors.txt new file mode 100644 index 0000000000000..75b9cf98dac0e --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks9.errors.txt @@ -0,0 +1,37 @@ +reachabilityChecks9.ts(7,7): error TS7027: Unreachable code detected. +reachabilityChecks9.ts(20,7): error TS7027: Unreachable code detected. + + +==== reachabilityChecks9.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/55562 + + function g(str: string) { + switch (str) { + case "a": + return; + console.log("1"); + ~~~~~~~~~~~~~~~~~ + console.log("2"); + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7027: Unreachable code detected. + case "b": + console.log("3"); + } + } + + function h(str: string) { + switch (str) { + case "a": + console.log("1"); + default: + return; + console.log("2"); + ~~~~~~~~~~~~~~~~~ + console.log("3"); + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS7027: Unreachable code detected. + case "b": + console.log("4"); + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/reachabilityChecks9.symbols b/tests/baselines/reference/reachabilityChecks9.symbols new file mode 100644 index 0000000000000..d50f997b9aabc --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks9.symbols @@ -0,0 +1,65 @@ +//// [tests/cases/compiler/reachabilityChecks9.ts] //// + +=== reachabilityChecks9.ts === +// https://github.com/microsoft/TypeScript/issues/55562 + +function g(str: string) { +>g : Symbol(g, Decl(reachabilityChecks9.ts, 0, 0)) +>str : Symbol(str, Decl(reachabilityChecks9.ts, 2, 11)) + + switch (str) { +>str : Symbol(str, Decl(reachabilityChecks9.ts, 2, 11)) + + case "a": + return; + console.log("1"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + console.log("2"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + case "b": + console.log("3"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + +function h(str: string) { +>h : Symbol(h, Decl(reachabilityChecks9.ts, 11, 1)) +>str : Symbol(str, Decl(reachabilityChecks9.ts, 13, 11)) + + switch (str) { +>str : Symbol(str, Decl(reachabilityChecks9.ts, 13, 11)) + + case "a": + console.log("1"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + default: + return; + console.log("2"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + console.log("3"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + case "b": + console.log("4"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + diff --git a/tests/baselines/reference/reachabilityChecks9.types b/tests/baselines/reference/reachabilityChecks9.types new file mode 100644 index 0000000000000..d428078568a98 --- /dev/null +++ b/tests/baselines/reference/reachabilityChecks9.types @@ -0,0 +1,132 @@ +//// [tests/cases/compiler/reachabilityChecks9.ts] //// + +=== reachabilityChecks9.ts === +// https://github.com/microsoft/TypeScript/issues/55562 + +function g(str: string) { +>g : (str: string) => void +> : ^ ^^ ^^^^^^^^^ +>str : string +> : ^^^^^^ + + switch (str) { +>str : string +> : ^^^^^^ + + case "a": +>"a" : "a" +> : ^^^ + + return; + console.log("1"); +>console.log("1") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"1" : "1" +> : ^^^ + + console.log("2"); +>console.log("2") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"2" : "2" +> : ^^^ + + case "b": +>"b" : "b" +> : ^^^ + + console.log("3"); +>console.log("3") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"3" : "3" +> : ^^^ + } +} + +function h(str: string) { +>h : (str: string) => void +> : ^ ^^ ^^^^^^^^^ +>str : string +> : ^^^^^^ + + switch (str) { +>str : string +> : ^^^^^^ + + case "a": +>"a" : "a" +> : ^^^ + + console.log("1"); +>console.log("1") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"1" : "1" +> : ^^^ + + default: + return; + console.log("2"); +>console.log("2") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"2" : "2" +> : ^^^ + + console.log("3"); +>console.log("3") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"3" : "3" +> : ^^^ + + case "b": +>"b" : "b" +> : ^^^ + + console.log("4"); +>console.log("4") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"4" : "4" +> : ^^^ + } +} + diff --git a/tests/baselines/reference/reachabilityChecksIgnored.js b/tests/baselines/reference/reachabilityChecksIgnored.js new file mode 100644 index 0000000000000..20ea3147dd9a5 --- /dev/null +++ b/tests/baselines/reference/reachabilityChecksIgnored.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/reachabilityChecksIgnored.ts] //// + +//// [reachabilityChecksIgnored.ts] +function a() { + throw new Error(""); + + // @ts-ignore + console.log("unreachable"); +} + +function b() { + throw new Error(""); + + // @ts-expect-error + console.log("unreachable"); +} + +//// [reachabilityChecksIgnored.js] +function a() { + throw new Error(""); + // @ts-ignore + console.log("unreachable"); +} +function b() { + throw new Error(""); + // @ts-expect-error + console.log("unreachable"); +} diff --git a/tests/baselines/reference/reachabilityChecksIgnored.symbols b/tests/baselines/reference/reachabilityChecksIgnored.symbols new file mode 100644 index 0000000000000..e41bf5334309a --- /dev/null +++ b/tests/baselines/reference/reachabilityChecksIgnored.symbols @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/reachabilityChecksIgnored.ts] //// + +=== reachabilityChecksIgnored.ts === +function a() { +>a : Symbol(a, Decl(reachabilityChecksIgnored.ts, 0, 0)) + + throw new Error(""); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + // @ts-ignore + console.log("unreachable"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +} + +function b() { +>b : Symbol(b, Decl(reachabilityChecksIgnored.ts, 5, 1)) + + throw new Error(""); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + // @ts-expect-error + console.log("unreachable"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +} diff --git a/tests/baselines/reference/reachabilityChecksIgnored.types b/tests/baselines/reference/reachabilityChecksIgnored.types new file mode 100644 index 0000000000000..8b1798d5ce288 --- /dev/null +++ b/tests/baselines/reference/reachabilityChecksIgnored.types @@ -0,0 +1,54 @@ +//// [tests/cases/compiler/reachabilityChecksIgnored.ts] //// + +=== reachabilityChecksIgnored.ts === +function a() { +>a : () => void +> : ^^^^^^^^^^ + + throw new Error(""); +>new Error("") : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ +>"" : "" +> : ^^ + + // @ts-ignore + console.log("unreachable"); +>console.log("unreachable") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"unreachable" : "unreachable" +> : ^^^^^^^^^^^^^ +} + +function b() { +>b : () => void +> : ^^^^^^^^^^ + + throw new Error(""); +>new Error("") : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ +>"" : "" +> : ^^ + + // @ts-expect-error + console.log("unreachable"); +>console.log("unreachable") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"unreachable" : "unreachable" +> : ^^^^^^^^^^^^^ +} diff --git a/tests/cases/compiler/reachabilityChecks10.ts b/tests/cases/compiler/reachabilityChecks10.ts new file mode 100644 index 0000000000000..e4f17b935ce0f --- /dev/null +++ b/tests/cases/compiler/reachabilityChecks10.ts @@ -0,0 +1,7 @@ +// @strict: true +// @noEmit: true +// @allowUnreachableCode: false + +throw new Error("") +console.log("1") +console.log("2") diff --git a/tests/cases/compiler/reachabilityChecks11.ts b/tests/cases/compiler/reachabilityChecks11.ts new file mode 100644 index 0000000000000..81dbcf3c7ad81 --- /dev/null +++ b/tests/cases/compiler/reachabilityChecks11.ts @@ -0,0 +1,76 @@ +// @allowUnreachableCode: false +// @preserveConstEnums: true + +// while (true); +var x = 1; + +module A { + while (true); + let x; +} + +module A1 { + do {} while(true); + module A { + interface F {} + } +} + +module A2 { + while (true); + module A { + var x = 1; + } +} + +module A3 { + while (true); + type T = string; +} + +module A4 { + while (true); + module A { + const enum E { X } + } +} + +function f1(x) { + if (x) { + return; + } + else { + throw new Error("123"); + } + var x; +} + +function f2() { + return; + class A { + } +} + +module B { + for (; ;); + module C { + } +} + +function f3() { + do { + } while (true); + enum E { + X = 1 + } +} + +function f4() { + if (true) { + throw new Error(); + } + const enum E { + X = 1 + } +} + diff --git a/tests/cases/compiler/reachabilityChecks9.ts b/tests/cases/compiler/reachabilityChecks9.ts new file mode 100644 index 0000000000000..601cdb65d4abd --- /dev/null +++ b/tests/cases/compiler/reachabilityChecks9.ts @@ -0,0 +1,29 @@ +// @strict: true +// @noEmit: true +// @allowUnreachableCode: false + +// https://github.com/microsoft/TypeScript/issues/55562 + +function g(str: string) { + switch (str) { + case "a": + return; + console.log("1"); + console.log("2"); + case "b": + console.log("3"); + } +} + +function h(str: string) { + switch (str) { + case "a": + console.log("1"); + default: + return; + console.log("2"); + console.log("3"); + case "b": + console.log("4"); + } +} diff --git a/tests/cases/compiler/reachabilityChecksIgnored.ts b/tests/cases/compiler/reachabilityChecksIgnored.ts new file mode 100644 index 0000000000000..baf32b57894d0 --- /dev/null +++ b/tests/cases/compiler/reachabilityChecksIgnored.ts @@ -0,0 +1,17 @@ +// @allowUnreachableCode: false +// @preserveConstEnums: true + + +function a() { + throw new Error(""); + + // @ts-ignore + console.log("unreachable"); +} + +function b() { + throw new Error(""); + + // @ts-expect-error + console.log("unreachable"); +} \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixUnreachableCode_noSuggestionIfDisabled.ts b/tests/cases/fourslash/codeFixUnreachableCode_noSuggestionIfDisabled.ts index 35ad3c430a335..8027f00275d96 100644 --- a/tests/cases/fourslash/codeFixUnreachableCode_noSuggestionIfDisabled.ts +++ b/tests/cases/fourslash/codeFixUnreachableCode_noSuggestionIfDisabled.ts @@ -2,6 +2,6 @@ // @allowUnreachableCode: true -////if (false) 0; +////if (false) [|0;|] verify.getSuggestionDiagnostics([]); diff --git a/tests/cases/fourslash/codeFixUnusedLabel_noSuggestionIfDisabled.ts b/tests/cases/fourslash/codeFixUnusedLabel_noSuggestionIfDisabled.ts index a7e504d2f66dd..e1a69b5bf3198 100644 --- a/tests/cases/fourslash/codeFixUnusedLabel_noSuggestionIfDisabled.ts +++ b/tests/cases/fourslash/codeFixUnusedLabel_noSuggestionIfDisabled.ts @@ -2,6 +2,6 @@ // @allowUnusedLabels: true -////foo: while (true) {} +////[|foo|]: while (true) {} verify.getSuggestionDiagnostics([]); From ec0f9c507d94cb46d8fdfbbf5301f4f835dc6351 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 14 Nov 2025 02:05:37 +0000 Subject: [PATCH 2/2] Update baselines --- .../reference/reachabilityChecks1.errors.txt | 54 ++++--------------- .../reference/reachabilityChecks11.js | 19 +++---- 2 files changed, 18 insertions(+), 55 deletions(-) diff --git a/tests/baselines/reference/reachabilityChecks1.errors.txt b/tests/baselines/reference/reachabilityChecks1.errors.txt index accc1d8fa7202..478dc4073348a 100644 --- a/tests/baselines/reference/reachabilityChecks1.errors.txt +++ b/tests/baselines/reference/reachabilityChecks1.errors.txt @@ -11,12 +11,8 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. ~~~~~~~~~~ -<<<<<<< HEAD module A { -======= - namespace A { - ~~~~~~~~~~~~~ ->>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) + ~~~~~~~~~~ while (true); ~~~~~~~~~~~~~~~~~ let x; @@ -25,18 +21,12 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. ~ -<<<<<<< HEAD module A1 { + ~~~~~~~~~~~ do {} while(true); + ~~~~~~~~~~~~~~~~~~~~~~ module A { -======= - namespace A1 { ~~~~~~~~~~~~~~ - do {} while(true); - ~~~~~~~~~~~~~~~~~~~~~~ - namespace A { - ~~~~~~~~~~~~~~~~~ ->>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) interface F {} ~~~~~~~~~~~~~~~~~~~~~~ } @@ -45,19 +35,12 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. ~ -<<<<<<< HEAD module A2 { + ~~~~~~~~~~~ while (true); + ~~~~~~~~~~~~~~~~~ module A { - ~~~~~~~~~~ -======= - namespace A2 { ~~~~~~~~~~~~~~ - while (true); - ~~~~~~~~~~~~~~~~~ - namespace A { - ~~~~~~~~~~~~~~~~~ ->>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) var x = 1; ~~~~~~~~~~~~~~~~~~ } @@ -66,12 +49,8 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. ~ -<<<<<<< HEAD module A3 { -======= - namespace A3 { - ~~~~~~~~~~~~~~ ->>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) + ~~~~~~~~~~~ while (true); ~~~~~~~~~~~~~~~~~ type T = string; @@ -80,19 +59,12 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. ~ -<<<<<<< HEAD module A4 { + ~~~~~~~~~~~ while (true); + ~~~~~~~~~~~~~~~~~ module A { - ~~~~~~~~~~ -======= - namespace A4 { ~~~~~~~~~~~~~~ - while (true); - ~~~~~~~~~~~~~~~~~ - namespace A { - ~~~~~~~~~~~~~~~~~ ->>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) const enum E { X } ~~~~~~~~~~~~~~~~~~~~~~~~~~ } @@ -120,18 +92,12 @@ reachabilityChecks1.ts(69,5): error TS7027: Unreachable code detected. !!! error TS7027: Unreachable code detected. } -<<<<<<< HEAD module B { + ~~~~~~~~~~ for (; ;); + ~~~~~~~~~~~~~~ module C { -======= - namespace B { - ~~~~~~~~~~~~~ - for (; ;); ~~~~~~~~~~~~~~ - namespace C { - ~~~~~~~~~~~~~~~~~ ->>>>>>> 09e31cf04a (Move unreachable checks to checker (#62751)) } ~~~~~ } diff --git a/tests/baselines/reference/reachabilityChecks11.js b/tests/baselines/reference/reachabilityChecks11.js index d115e58e816cb..1e69b95ff90ca 100644 --- a/tests/baselines/reference/reachabilityChecks11.js +++ b/tests/baselines/reference/reachabilityChecks11.js @@ -83,7 +83,7 @@ var A; (function (A) { while (true) ; - var x; + let x; })(A || (A = {})); var A1; (function (A1) { @@ -93,7 +93,7 @@ var A2; (function (A2) { while (true) ; - var A; + let A; (function (A) { var x = 1; })(A || (A = {})); @@ -107,9 +107,9 @@ var A4; (function (A4) { while (true) ; - var A; + let A; (function (A) { - var E; + let E; (function (E) { E[E["X"] = 0] = "X"; })(E || (E = {})); @@ -126,11 +126,8 @@ function f1(x) { } function f2() { return; - var A = /** @class */ (function () { - function A() { - } - return A; - }()); + class A { + } } var B; (function (B) { @@ -140,7 +137,7 @@ var B; function f3() { do { } while (true); - var E; + let E; (function (E) { E[E["X"] = 1] = "X"; })(E || (E = {})); @@ -149,7 +146,7 @@ function f4() { if (true) { throw new Error(); } - var E; + let E; (function (E) { E[E["X"] = 1] = "X"; })(E || (E = {}));