Fixed crash when adding unreachable code diagnostic in situations with missing nodes (#62914)

This commit is contained in:
Mateusz Burzyński
2025-12-19 14:18:44 +01:00
committed by GitHub
parent b78f0899ab
commit 2dfdbbabae
6 changed files with 278 additions and 6 deletions

View File

@@ -383,6 +383,7 @@ import {
getTextOfPropertyName,
getThisContainer,
getThisParameter,
getTokenPosOfNode,
getTrailingSemicolonDeferringWriter,
getTypeParameterFromJsDoc,
getUseDefineForClassFields,
@@ -49232,8 +49233,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const sourceFile = getSourceFileOfNode(node);
let start = node.pos;
let end = node.end;
let startNode = node;
let endNode = node;
const parent = node.parent;
if (canHaveStatements(parent)) {
@@ -49263,13 +49264,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
reportedUnreachableNodes.add(nextNode);
}
start = statements[first].pos;
end = statements[last].end;
startNode = statements[first];
endNode = statements[last];
}
}
start = skipTrivia(sourceFile.text, start);
addErrorOrSuggestion(compilerOptions.allowUnreachableCode === false, createFileDiagnostic(sourceFile, start, end - start, Diagnostics.Unreachable_code_detected));
const start = getTokenPosOfNode(startNode, sourceFile);
addErrorOrSuggestion(compilerOptions.allowUnreachableCode === false, createFileDiagnostic(sourceFile, start, endNode.end - start, Diagnostics.Unreachable_code_detected));
return true;
}

View File

@@ -0,0 +1,120 @@
reachabilityChecksNoCrash1.ts(1,23): error TS7010: 'arrayFromAsync', which lacks return-type annotation, implicitly has an 'any' return type.
reachabilityChecksNoCrash1.ts(1,41): error TS7006: Parameter 'asyncIterable' implicitly has an 'any' type.
reachabilityChecksNoCrash1.ts(1,54): error TS2300: Duplicate identifier '(Missing)'.
reachabilityChecksNoCrash1.ts(1,54): error TS7006: Parameter '(Missing)' implicitly has an 'any' type.
reachabilityChecksNoCrash1.ts(1,54): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(1,55): error TS1138: Parameter declaration expected.
reachabilityChecksNoCrash1.ts(1,57): error TS7006: Parameter 'AsyncIterable' implicitly has an 'any' type.
reachabilityChecksNoCrash1.ts(1,70): error TS2300: Duplicate identifier '(Missing)'.
reachabilityChecksNoCrash1.ts(1,70): error TS7006: Parameter '(Missing)' implicitly has an 'any' type.
reachabilityChecksNoCrash1.ts(1,70): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(1,71): error TS7006: Parameter 'T' implicitly has an 'any' type.
reachabilityChecksNoCrash1.ts(1,72): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(1,73): error TS1109: Expression expected.
reachabilityChecksNoCrash1.ts(1,74): error TS1128: Declaration or statement expected.
reachabilityChecksNoCrash1.ts(1,76): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{ const: any; for: any; of: any; asyncIterable: any; out: any; "": any; }'.
reachabilityChecksNoCrash1.ts(1,84): error TS2304: Cannot find name 'T'.
reachabilityChecksNoCrash1.ts(1,86): error TS1011: An element access expression should take an argument.
reachabilityChecksNoCrash1.ts(2,11): error TS1005: ':' expected.
reachabilityChecksNoCrash1.ts(2,11): error TS2304: Cannot find name 'out'.
reachabilityChecksNoCrash1.ts(2,19): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(3,9): error TS1005: ':' expected.
reachabilityChecksNoCrash1.ts(3,16): error TS1109: Expression expected.
reachabilityChecksNoCrash1.ts(3,22): error TS1005: ':' expected.
reachabilityChecksNoCrash1.ts(3,22): error TS2304: Cannot find name 'v'.
reachabilityChecksNoCrash1.ts(3,24): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(3,24): error TS18004: No value exists in scope for the shorthand property 'of'. Either declare one or provide an initializer.
reachabilityChecksNoCrash1.ts(3,27): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(3,27): error TS18004: No value exists in scope for the shorthand property 'asyncIterable'. Either declare one or provide an initializer.
reachabilityChecksNoCrash1.ts(3,40): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(3,42): error TS1136: Property assignment expected.
reachabilityChecksNoCrash1.ts(4,9): error TS18004: No value exists in scope for the shorthand property 'out'. Either declare one or provide an initializer.
reachabilityChecksNoCrash1.ts(4,12): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(4,24): error TS2304: Cannot find name 'v'.
reachabilityChecksNoCrash1.ts(4,26): error TS1005: ',' expected.
reachabilityChecksNoCrash1.ts(7,1): error TS1109: Expression expected.
==== reachabilityChecksNoCrash1.ts (35 errors) ====
export async function arrayFromAsync<T>(asyncIterable!: AsyncIterable<T>): Promise<T[]> {
~~~~~~~~~~~~~~
!!! error TS7010: 'arrayFromAsync', which lacks return-type annotation, implicitly has an 'any' return type.
~~~~~~~~~~~~~
!!! error TS7006: Parameter 'asyncIterable' implicitly has an 'any' type.
!!! error TS2300: Duplicate identifier '(Missing)'.
!!! error TS7006: Parameter '(Missing)' implicitly has an 'any' type.
~
!!! error TS1005: ',' expected.
~
!!! error TS1138: Parameter declaration expected.
~~~~~~~~~~~~~
!!! error TS7006: Parameter 'AsyncIterable' implicitly has an 'any' type.
!!! error TS2300: Duplicate identifier '(Missing)'.
!!! error TS7006: Parameter '(Missing)' implicitly has an 'any' type.
~
!!! error TS1005: ',' expected.
~
!!! error TS7006: Parameter 'T' implicitly has an 'any' type.
~
!!! error TS1005: ',' expected.
~
!!! error TS1109: Expression expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~
~
!!! error TS2304: Cannot find name 'T'.
!!! error TS1011: An element access expression should take an argument.
const out = [];
~~~~~~~~~~~~~~~~~~~
~~~
!!! error TS1005: ':' expected.
~~~
!!! error TS2304: Cannot find name 'out'.
~
!!! error TS1005: ',' expected.
for await (const v of asyncIterable) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~
!!! error TS1005: ':' expected.
~~~~~
!!! error TS1109: Expression expected.
~
!!! error TS1005: ':' expected.
~
!!! error TS2304: Cannot find name 'v'.
~~
!!! error TS1005: ',' expected.
~~
!!! error TS18004: No value exists in scope for the shorthand property 'of'. Either declare one or provide an initializer.
~~~~~~~~~~~~~
!!! error TS1005: ',' expected.
~~~~~~~~~~~~~
!!! error TS18004: No value exists in scope for the shorthand property 'asyncIterable'. Either declare one or provide an initializer.
~
!!! error TS1005: ',' expected.
~
!!! error TS1136: Property assignment expected.
out.push(await v);
~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
!!! error TS18004: No value exists in scope for the shorthand property 'out'. Either declare one or provide an initializer.
~
!!! error TS1005: ',' expected.
~
!!! error TS2304: Cannot find name 'v'.
~
!!! error TS1005: ',' expected.
}
~~~~~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{ const: any; for: any; of: any; asyncIterable: any; out: any; "": any; }'.
return out;
}
~
!!! error TS1109: Expression expected.

View File

@@ -0,0 +1,22 @@
//// [tests/cases/compiler/reachabilityChecksNoCrash1.ts] ////
//// [reachabilityChecksNoCrash1.ts]
export async function arrayFromAsync<T>(asyncIterable!: AsyncIterable<T>): Promise<T[]> {
const out = [];
for await (const v of asyncIterable) {
out.push(await v);
}
return out;
}
//// [reachabilityChecksNoCrash1.js]
> ;
Promise < T[] > {
const: out = [],
for: await (), const: v, of, asyncIterable,
out, : .push(await v)
};
return out;
;
export {};

View File

@@ -0,0 +1,29 @@
//// [tests/cases/compiler/reachabilityChecksNoCrash1.ts] ////
=== reachabilityChecksNoCrash1.ts ===
export async function arrayFromAsync<T>(asyncIterable!: AsyncIterable<T>): Promise<T[]> {
>arrayFromAsync : Symbol(arrayFromAsync, Decl(reachabilityChecksNoCrash1.ts, 0, 0))
>T : Symbol(T, Decl(reachabilityChecksNoCrash1.ts, 0, 37), Decl(reachabilityChecksNoCrash1.ts, 0, 70))
>asyncIterable : Symbol(asyncIterable, Decl(reachabilityChecksNoCrash1.ts, 0, 40))
> : Symbol((Missing), Decl(reachabilityChecksNoCrash1.ts, 0, 53))
>AsyncIterable : Symbol(AsyncIterable, Decl(reachabilityChecksNoCrash1.ts, 0, 55))
> : Symbol((Missing), Decl(reachabilityChecksNoCrash1.ts, 0, 69))
>T : Symbol(T, Decl(reachabilityChecksNoCrash1.ts, 0, 37), Decl(reachabilityChecksNoCrash1.ts, 0, 70))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
const out = [];
>const : Symbol(const, Decl(reachabilityChecksNoCrash1.ts, 0, 89), Decl(reachabilityChecksNoCrash1.ts, 2, 15))
for await (const v of asyncIterable) {
>for : Symbol(for, Decl(reachabilityChecksNoCrash1.ts, 1, 19))
>const : Symbol(const, Decl(reachabilityChecksNoCrash1.ts, 0, 89), Decl(reachabilityChecksNoCrash1.ts, 2, 15))
>of : Symbol(of, Decl(reachabilityChecksNoCrash1.ts, 2, 22))
>asyncIterable : Symbol(asyncIterable, Decl(reachabilityChecksNoCrash1.ts, 2, 25))
out.push(await v);
>out : Symbol(out, Decl(reachabilityChecksNoCrash1.ts, 2, 42))
> : Symbol((Missing), Decl(reachabilityChecksNoCrash1.ts, 3, 11))
}
return out;
}

View File

@@ -0,0 +1,90 @@
//// [tests/cases/compiler/reachabilityChecksNoCrash1.ts] ////
=== reachabilityChecksNoCrash1.ts ===
export async function arrayFromAsync<T>(asyncIterable!: AsyncIterable<T>): Promise<T[]> {
>arrayFromAsync : <T>(asyncIterable: any, : any, AsyncIterable: any, : any, T: any) => any
> : ^ ^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
>asyncIterable : any
> : ^^^
> : any
> : ^^^
>AsyncIterable : any
> : ^^^
> : any
> : ^^^
>T : any
> : ^^^
>> : boolean
> : ^^^^^^^
> : any
> : ^^^
> : any
> : ^^^
>Promise<T[]> { const out = []; for await (const v of asyncIterable) { out.push(await v); } : boolean
> : ^^^^^^^
>Promise<T[] : boolean
> : ^^^^^^^
>Promise : PromiseConstructor
> : ^^^^^^^^^^^^^^^^^^
>T[] : any
> : ^^^
>T : any
> : ^^^
> : any
> : ^^^
>{ const out = []; for await (const v of asyncIterable) { out.push(await v); } : { const: any; for: any; of: any; asyncIterable: any; out: any; "": any; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const out = [];
>const : never[]
> : ^^^^^^^
>out = [] : never[]
> : ^^^^^^^
>out : any
> : ^^^
>[] : never[]
> : ^^^^^^^
for await (const v of asyncIterable) {
>for : any
> : ^^^
>await ( : any
> : ^^^
>( : any
> : ^^^
> : any
> : ^^^
>const : never[]
> : ^^^^^^^
>v : any
> : ^^^
>of : any
> : ^^^
>asyncIterable : any
> : ^^^
out.push(await v);
>out : any
> : ^^^
> : any
> : ^^^
>.push(await v) : any
> : ^^^
>.push : any
> : ^^^
> : any
> : ^^^
>push : any
> : ^^^
>await v : any
> : ^^^
>v : any
> : ^^^
}
return out;
>out : any
> : ^^^
}
> : any
> : ^^^

View File

@@ -0,0 +1,10 @@
// @strict: true
// @target: esnext
export async function arrayFromAsync<T>(asyncIterable!: AsyncIterable<T>): Promise<T[]> {
const out = [];
for await (const v of asyncIterable) {
out.push(await v);
}
return out;
}