diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8fa3c4fce2a4a..8334be76f49aa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21027,6 +21027,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // that perpetually generate new type identities, so we stop the recursion here by yielding the error type. tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount }); error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); + // set this to a max value to "propagate" the error through any further instantiations within the currently checked node + // this can skip a bunch of redundant work in the case of hitting the depth limit + instantiationCount = 5000000; return errorType; } const index = findActiveMapper(mapper); diff --git a/tests/baselines/reference/recursiveConditionalCrash5.errors.txt b/tests/baselines/reference/recursiveConditionalCrash5.errors.txt new file mode 100644 index 0000000000000..b4919b9e65cd9 --- /dev/null +++ b/tests/baselines/reference/recursiveConditionalCrash5.errors.txt @@ -0,0 +1,21 @@ +recursiveConditionalCrash5.ts(13,6): error TS2589: Type instantiation is excessively deep and possibly infinite. + + +==== recursiveConditionalCrash5.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/62966 + + type Prepend = T extends unknown + ? ((arg: Elm, ...rest: T) => void) extends (...args: infer T2) => void + ? T2 + : never + : never; + + type ExactExtract = (T extends U ? U extends T ? T : never : never) & string; + + type Conv = { + 0: [T]; + 1: Prepend>>; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + }[U extends T ? 0 : 1]; + \ No newline at end of file diff --git a/tests/baselines/reference/recursiveConditionalCrash5.symbols b/tests/baselines/reference/recursiveConditionalCrash5.symbols new file mode 100644 index 0000000000000..d77c6f1c863ea --- /dev/null +++ b/tests/baselines/reference/recursiveConditionalCrash5.symbols @@ -0,0 +1,58 @@ +//// [tests/cases/compiler/recursiveConditionalCrash5.ts] //// + +=== recursiveConditionalCrash5.ts === +// https://github.com/microsoft/TypeScript/issues/62966 + +type Prepend = T extends unknown +>Prepend : Symbol(Prepend, Decl(recursiveConditionalCrash5.ts, 0, 0)) +>Elm : Symbol(Elm, Decl(recursiveConditionalCrash5.ts, 2, 13)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 2, 17)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 2, 17)) + + ? ((arg: Elm, ...rest: T) => void) extends (...args: infer T2) => void +>arg : Symbol(arg, Decl(recursiveConditionalCrash5.ts, 3, 6)) +>Elm : Symbol(Elm, Decl(recursiveConditionalCrash5.ts, 2, 13)) +>rest : Symbol(rest, Decl(recursiveConditionalCrash5.ts, 3, 15)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 2, 17)) +>args : Symbol(args, Decl(recursiveConditionalCrash5.ts, 3, 46)) +>T2 : Symbol(T2, Decl(recursiveConditionalCrash5.ts, 3, 60)) + + ? T2 +>T2 : Symbol(T2, Decl(recursiveConditionalCrash5.ts, 3, 60)) + + : never + : never; + +type ExactExtract = (T extends U ? U extends T ? T : never : never) & string; +>ExactExtract : Symbol(ExactExtract, Decl(recursiveConditionalCrash5.ts, 6, 10)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 8, 18)) +>U : Symbol(U, Decl(recursiveConditionalCrash5.ts, 8, 20)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 8, 18)) +>U : Symbol(U, Decl(recursiveConditionalCrash5.ts, 8, 20)) +>U : Symbol(U, Decl(recursiveConditionalCrash5.ts, 8, 20)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 8, 18)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 8, 18)) + +type Conv = { +>Conv : Symbol(Conv, Decl(recursiveConditionalCrash5.ts, 8, 83)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 10, 10)) +>U : Symbol(U, Decl(recursiveConditionalCrash5.ts, 10, 12)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 10, 10)) + + 0: [T]; +>0 : Symbol(0, Decl(recursiveConditionalCrash5.ts, 10, 23)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 10, 10)) + + 1: Prepend>>; +>1 : Symbol(1, Decl(recursiveConditionalCrash5.ts, 11, 9)) +>Prepend : Symbol(Prepend, Decl(recursiveConditionalCrash5.ts, 0, 0)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 10, 10)) +>Conv : Symbol(Conv, Decl(recursiveConditionalCrash5.ts, 8, 83)) +>ExactExtract : Symbol(ExactExtract, Decl(recursiveConditionalCrash5.ts, 6, 10)) +>U : Symbol(U, Decl(recursiveConditionalCrash5.ts, 10, 12)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 10, 10)) + +}[U extends T ? 0 : 1]; +>U : Symbol(U, Decl(recursiveConditionalCrash5.ts, 10, 12)) +>T : Symbol(T, Decl(recursiveConditionalCrash5.ts, 10, 10)) + diff --git a/tests/baselines/reference/recursiveConditionalCrash5.types b/tests/baselines/reference/recursiveConditionalCrash5.types new file mode 100644 index 0000000000000..c50cb029af773 --- /dev/null +++ b/tests/baselines/reference/recursiveConditionalCrash5.types @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/recursiveConditionalCrash5.ts] //// + +=== Performance Stats === +Instantiation count: 5,000 + +=== recursiveConditionalCrash5.ts === +// https://github.com/microsoft/TypeScript/issues/62966 + +type Prepend = T extends unknown +>Prepend : Prepend +> : ^^^^^^^^^^^^^^^ + + ? ((arg: Elm, ...rest: T) => void) extends (...args: infer T2) => void +>arg : Elm +> : ^^^ +>rest : T +> : ^ +>args : T2 +> : ^^ + + ? T2 + : never + : never; + +type ExactExtract = (T extends U ? U extends T ? T : never : never) & string; +>ExactExtract : ExactExtract +> : ^^^^^^^^^^^^^^^^^^ + +type Conv = { +>Conv : Conv +> : ^^^^^^^^^^ + + 0: [T]; +>0 : [T] +> : ^^^ + + 1: Prepend>>; +>1 : Prepend, ExactExtract>> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}[U extends T ? 0 : 1]; + diff --git a/tests/cases/compiler/recursiveConditionalCrash5.ts b/tests/cases/compiler/recursiveConditionalCrash5.ts new file mode 100644 index 0000000000000..6cf9759d4eae6 --- /dev/null +++ b/tests/cases/compiler/recursiveConditionalCrash5.ts @@ -0,0 +1,17 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/62966 + +type Prepend = T extends unknown + ? ((arg: Elm, ...rest: T) => void) extends (...args: infer T2) => void + ? T2 + : never + : never; + +type ExactExtract = (T extends U ? U extends T ? T : never : never) & string; + +type Conv = { + 0: [T]; + 1: Prepend>>; +}[U extends T ? 0 : 1];