Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36603,7 +36603,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
else {
Debug.fail("No error for last overload signature");
// Fallback: Generate a generic error when no specific error can be determined
// This replaces the Debug.fail() to prevent compiler crashes
// See: https://github.com/microsoft/TypeScript/issues/61524
const fallbackChain = chainDiagnosticMessages(
/*details*/ undefined,
Diagnostics.No_overload_matches_this_call,
);
const errorNode = getErrorNodeForCallNode(node);
const fallbackDiag = createDiagnosticForNodeFromMessageChain(
getSourceFileOfNode(errorNode),
errorNode,
fallbackChain,
/*relatedInformation*/ undefined,
);

diagnostics.add(fallbackDiag);
}
}
else {
Expand All @@ -36624,7 +36639,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
allDiagnostics.push(diags);
}
else {
Debug.fail("No error for 3 or fewer overload signatures");
// Fallback: Generate a generic error for this overload candidate
// This prevents crashes when processing multiple overload signatures
const fallbackChain = chainDiagnosticMessages(
/*details*/ undefined,
Diagnostics.Overload_0_of_1_2_gave_the_following_error,
i + 1,
candidates.length,
signatureToString(c),
);
const errorNode = getErrorNodeForCallNode(node);
const fallbackDiag = createDiagnosticForNodeFromMessageChain(
getSourceFileOfNode(errorNode),
errorNode,
fallbackChain,
/*relatedInformation*/ undefined,
);
allDiagnostics.push([fallbackDiag]);
}
i++;
}
Expand Down
28 changes: 28 additions & 0 deletions tests/baselines/reference/issue61524DebugFailureCrash.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
issue61524DebugFailureCrash.ts(10,37): error TS2550: Property 'entries' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2017' or later.
issue61524DebugFailureCrash.ts(11,9): error TS2769: No overload matches this call.


==== issue61524DebugFailureCrash.ts (2 errors) ====
// Exact reproduction from https://github.com/microsoft/TypeScript/issues/61524
// This code causes "Debug Failure. No error for last overload signature"

type Generic<T> = T extends any[] ? T[number] : T[keyof T];

export function testFn<A extends Record<string, any>>(
obj: A,
cb: (b: Generic<Partial<A>>) => any
) {
for (const [key, val] of Object.entries(obj)) {
~~~~~~~
!!! error TS2550: Property 'entries' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2017' or later.
cb(val as Generic<A>);
~~
!!! error TS2769: No overload matches this call.
}
}

// Usage that triggers the crash
testFn(
{ foo: "bar", num: 42 },
(val) => console.log(val) // Type inference here causes the issue
);
61 changes: 61 additions & 0 deletions tests/baselines/reference/issue61524DebugFailureCrash.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//// [tests/cases/compiler/issue61524DebugFailureCrash.ts] ////

=== issue61524DebugFailureCrash.ts ===
// Exact reproduction from https://github.com/microsoft/TypeScript/issues/61524
// This code causes "Debug Failure. No error for last overload signature"

type Generic<T> = T extends any[] ? T[number] : T[keyof T];
>Generic : Symbol(Generic, Decl(issue61524DebugFailureCrash.ts, 0, 0))
>T : Symbol(T, Decl(issue61524DebugFailureCrash.ts, 3, 13))
>T : Symbol(T, Decl(issue61524DebugFailureCrash.ts, 3, 13))
>T : Symbol(T, Decl(issue61524DebugFailureCrash.ts, 3, 13))
>T : Symbol(T, Decl(issue61524DebugFailureCrash.ts, 3, 13))
>T : Symbol(T, Decl(issue61524DebugFailureCrash.ts, 3, 13))

export function testFn<A extends Record<string, any>>(
>testFn : Symbol(testFn, Decl(issue61524DebugFailureCrash.ts, 3, 59))
>A : Symbol(A, Decl(issue61524DebugFailureCrash.ts, 5, 23))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))

obj: A,
>obj : Symbol(obj, Decl(issue61524DebugFailureCrash.ts, 5, 54))
>A : Symbol(A, Decl(issue61524DebugFailureCrash.ts, 5, 23))

cb: (b: Generic<Partial<A>>) => any
>cb : Symbol(cb, Decl(issue61524DebugFailureCrash.ts, 6, 11))
>b : Symbol(b, Decl(issue61524DebugFailureCrash.ts, 7, 9))
>Generic : Symbol(Generic, Decl(issue61524DebugFailureCrash.ts, 0, 0))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>A : Symbol(A, Decl(issue61524DebugFailureCrash.ts, 5, 23))

) {
for (const [key, val] of Object.entries(obj)) {
>key : Symbol(key, Decl(issue61524DebugFailureCrash.ts, 9, 16))
>val : Symbol(val, Decl(issue61524DebugFailureCrash.ts, 9, 20))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>obj : Symbol(obj, Decl(issue61524DebugFailureCrash.ts, 5, 54))

cb(val as Generic<A>);
>cb : Symbol(cb, Decl(issue61524DebugFailureCrash.ts, 6, 11))
>val : Symbol(val, Decl(issue61524DebugFailureCrash.ts, 9, 20))
>Generic : Symbol(Generic, Decl(issue61524DebugFailureCrash.ts, 0, 0))
>A : Symbol(A, Decl(issue61524DebugFailureCrash.ts, 5, 23))
}
}

// Usage that triggers the crash
testFn(
>testFn : Symbol(testFn, Decl(issue61524DebugFailureCrash.ts, 3, 59))

{ foo: "bar", num: 42 },
>foo : Symbol(foo, Decl(issue61524DebugFailureCrash.ts, 16, 5))
>num : Symbol(num, Decl(issue61524DebugFailureCrash.ts, 16, 17))

(val) => console.log(val) // Type inference here causes the issue
>val : Symbol(val, Decl(issue61524DebugFailureCrash.ts, 17, 5))
>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, --, --))
>val : Symbol(val, Decl(issue61524DebugFailureCrash.ts, 17, 5))

);
89 changes: 89 additions & 0 deletions tests/baselines/reference/issue61524DebugFailureCrash.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//// [tests/cases/compiler/issue61524DebugFailureCrash.ts] ////

=== issue61524DebugFailureCrash.ts ===
// Exact reproduction from https://github.com/microsoft/TypeScript/issues/61524
// This code causes "Debug Failure. No error for last overload signature"

type Generic<T> = T extends any[] ? T[number] : T[keyof T];
>Generic : Generic<T>
> : ^^^^^^^^^^

export function testFn<A extends Record<string, any>>(
>testFn : <A extends Record<string, any>>(obj: A, cb: (b: Generic<Partial<A>>) => any) => void
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^

obj: A,
>obj : A
> : ^

cb: (b: Generic<Partial<A>>) => any
>cb : (b: Generic<Partial<A>>) => any
> : ^ ^^ ^^^^^
>b : Generic<Partial<A>>
> : ^^^^^^^^^^^^^^^^^^^

) {
for (const [key, val] of Object.entries(obj)) {
>key : any
> : ^^^
>val : any
> : ^^^
>Object.entries(obj) : any
> : ^^^
>Object.entries : any
> : ^^^
>Object : ObjectConstructor
> : ^^^^^^^^^^^^^^^^^
>entries : any
> : ^^^
>obj : A
> : ^

cb(val as Generic<A>);
>cb(val as Generic<A>) : any
> : ^^^
>cb : (b: Generic<Partial<A>>) => any
> : ^ ^^ ^^^^^
>val as Generic<A> : Generic<A>
> : ^^^^^^^^^^
>val : any
> : ^^^
}
}

// Usage that triggers the crash
testFn(
>testFn( { foo: "bar", num: 42 }, (val) => console.log(val) // Type inference here causes the issue) : void
> : ^^^^
>testFn : <A extends Record<string, any>>(obj: A, cb: (b: Generic<Partial<A>>) => any) => void
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^

{ foo: "bar", num: 42 },
>{ foo: "bar", num: 42 } : { foo: string; num: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>foo : string
> : ^^^^^^
>"bar" : "bar"
> : ^^^^^
>num : number
> : ^^^^^^
>42 : 42
> : ^^

(val) => console.log(val) // Type inference here causes the issue
>(val) => console.log(val) : (val: string | number | undefined) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>val : string | number | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>console.log(val) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>val : string | number | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^

);
22 changes: 22 additions & 0 deletions tests/cases/compiler/issue61524DebugFailureCrash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @strict: true
// @noEmit: true

// Exact reproduction from https://github.com/microsoft/TypeScript/issues/61524
// This code causes "Debug Failure. No error for last overload signature"

type Generic<T> = T extends any[] ? T[number] : T[keyof T];

export function testFn<A extends Record<string, any>>(
obj: A,
cb: (b: Generic<Partial<A>>) => any
) {
for (const [key, val] of Object.entries(obj)) {
cb(val as Generic<A>);
}
}

// Usage that triggers the crash
testFn(
{ foo: "bar", num: 42 },
(val) => console.log(val) // Type inference here causes the issue
);