diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e9c72ec48319..3d2243fa9fc3b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17773,20 +17773,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { while (true) { if (tailCount === 1000) { error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); - result = errorType; - break; + return errorType; + } + const checkType = instantiateType(getActualTypeVariable(root.checkType), mapper); + const extendsType = instantiateType(root.extendsType, mapper); + if (checkType === errorType || extendsType === errorType) { + return errorType; + } + if (checkType === wildcardType || extendsType === wildcardType) { + return wildcardType; } // When the check and extends types are simple tuple types of the same arity, we defer resolution of the // conditional type when any tuple elements are generic. This is such that non-distributable conditional // types can be written `[X] extends [Y] ? ...` and be deferred similarly to `X extends Y ? ...`. const checkTuples = isSimpleTupleType(root.node.checkType) && isSimpleTupleType(root.node.extendsType) && length((root.node.checkType as TupleTypeNode).elements) === length((root.node.extendsType as TupleTypeNode).elements); - const checkType = instantiateType(getActualTypeVariable(root.checkType), mapper); const checkTypeDeferred = isDeferredType(checkType, checkTuples); - const extendsType = instantiateType(root.extendsType, mapper); - if (checkType === wildcardType || extendsType === wildcardType) { - return wildcardType; - } let combinedMapper: TypeMapper | undefined; if (root.inferTypeParameters) { // When we're looking at making an inference for an infer type, when we get its constraint, it'll automagically be diff --git a/tests/baselines/reference/excessivelyLargeTupleSpread.errors.txt b/tests/baselines/reference/excessivelyLargeTupleSpread.errors.txt index 0b5e44369c7d6..fdb940b6cdf20 100644 --- a/tests/baselines/reference/excessivelyLargeTupleSpread.errors.txt +++ b/tests/baselines/reference/excessivelyLargeTupleSpread.errors.txt @@ -1,10 +1,9 @@ -tests/cases/compiler/excessivelyLargeTupleSpread.ts(6,10): error TS2589: Type instantiation is excessively deep and possibly infinite. tests/cases/compiler/excessivelyLargeTupleSpread.ts(6,10): error TS2799: Type produces a tuple type that is too large to represent. tests/cases/compiler/excessivelyLargeTupleSpread.ts(22,12): error TS2799: Type produces a tuple type that is too large to represent. tests/cases/compiler/excessivelyLargeTupleSpread.ts(38,13): error TS2800: Expression produces a tuple type that is too large to represent. -==== tests/cases/compiler/excessivelyLargeTupleSpread.ts (4 errors) ==== +==== tests/cases/compiler/excessivelyLargeTupleSpread.ts (3 errors) ==== // #41771 type BuildTuple = @@ -12,8 +11,6 @@ tests/cases/compiler/excessivelyLargeTupleSpread.ts(38,13): error TS2800: Expres type A = BuildTuple<3> ~~~~~~~~~~~~~ -!!! error TS2589: Type instantiation is excessively deep and possibly infinite. - ~~~~~~~~~~~~~ !!! error TS2799: Type produces a tuple type that is too large to represent. type T0 = [any]; diff --git a/tests/baselines/reference/recursiveConditionalCrash4.errors.txt b/tests/baselines/reference/recursiveConditionalCrash4.errors.txt new file mode 100644 index 0000000000000..f66921b5114bd --- /dev/null +++ b/tests/baselines/reference/recursiveConditionalCrash4.errors.txt @@ -0,0 +1,42 @@ +tests/cases/compiler/recursiveConditionalCrash4.ts(7,16): error TS2503: Cannot find namespace 'StrIter'. +tests/cases/compiler/recursiveConditionalCrash4.ts(8,5): error TS2503: Cannot find namespace 'StrIter'. +tests/cases/compiler/recursiveConditionalCrash4.ts(9,25): error TS2304: Cannot find name 'Add'. +tests/cases/compiler/recursiveConditionalCrash4.ts(9,37): error TS2503: Cannot find namespace 'StrIter'. +tests/cases/compiler/recursiveConditionalCrash4.ts(10,7): error TS2589: Type instantiation is excessively deep and possibly infinite. +tests/cases/compiler/recursiveConditionalCrash4.ts(10,31): error TS2503: Cannot find namespace 'StrIter'. +tests/cases/compiler/recursiveConditionalCrash4.ts(16,7): error TS2589: Type instantiation is excessively deep and possibly infinite. + + +==== tests/cases/compiler/recursiveConditionalCrash4.ts (7 errors) ==== + // Repros from #53783 + + type LengthDown< + Str extends string, + Length extends number | bigint, + It + > = It extends StrIter.Iterator + ~~~~~~~ +!!! error TS2503: Cannot find namespace 'StrIter'. + ? StrIter.CutAt extends `${infer $Rest}` + ~~~~~~~ +!!! error TS2503: Cannot find namespace 'StrIter'. + ? LengthDown<$Rest, Add>, It> + ~~~ +!!! error TS2304: Cannot find name 'Add'. + ~~~~~~~ +!!! error TS2503: Cannot find namespace 'StrIter'. + : LengthDown> + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + ~~~~~~~ +!!! error TS2503: Cannot find namespace 'StrIter'. + : Length; + + type Foo = T extends unknown + ? unknown extends `${infer $Rest}` + ? Foo + : Foo + ~~~~~~~~~~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + : unknown; + \ No newline at end of file diff --git a/tests/baselines/reference/recursiveConditionalCrash4.symbols b/tests/baselines/reference/recursiveConditionalCrash4.symbols new file mode 100644 index 0000000000000..74abf55ef0848 --- /dev/null +++ b/tests/baselines/reference/recursiveConditionalCrash4.symbols @@ -0,0 +1,65 @@ +=== tests/cases/compiler/recursiveConditionalCrash4.ts === +// Repros from #53783 + +type LengthDown< +>LengthDown : Symbol(LengthDown, Decl(recursiveConditionalCrash4.ts, 0, 0)) + + Str extends string, +>Str : Symbol(Str, Decl(recursiveConditionalCrash4.ts, 2, 16)) + + Length extends number | bigint, +>Length : Symbol(Length, Decl(recursiveConditionalCrash4.ts, 3, 21)) + + It +>It : Symbol(It, Decl(recursiveConditionalCrash4.ts, 4, 33)) + +> = It extends StrIter.Iterator +>It : Symbol(It, Decl(recursiveConditionalCrash4.ts, 4, 33)) +>StrIter : Symbol(StrIter) +>Iterator : Symbol(StrIter.Iterator) + + ? StrIter.CutAt extends `${infer $Rest}` +>StrIter : Symbol(StrIter) +>CutAt : Symbol(StrIter.CutAt) +>Str : Symbol(Str, Decl(recursiveConditionalCrash4.ts, 2, 16)) +>It : Symbol(It, Decl(recursiveConditionalCrash4.ts, 4, 33)) +>$Rest : Symbol($Rest, Decl(recursiveConditionalCrash4.ts, 7, 43)) + + ? LengthDown<$Rest, Add>, It> +>LengthDown : Symbol(LengthDown, Decl(recursiveConditionalCrash4.ts, 0, 0)) +>$Rest : Symbol($Rest, Decl(recursiveConditionalCrash4.ts, 7, 43)) +>Add : Symbol(Add) +>Length : Symbol(Length, Decl(recursiveConditionalCrash4.ts, 3, 21)) +>StrIter : Symbol(StrIter) +>Value : Symbol(StrIter.Value) +>It : Symbol(It, Decl(recursiveConditionalCrash4.ts, 4, 33)) +>It : Symbol(It, Decl(recursiveConditionalCrash4.ts, 4, 33)) + + : LengthDown> +>LengthDown : Symbol(LengthDown, Decl(recursiveConditionalCrash4.ts, 0, 0)) +>Str : Symbol(Str, Decl(recursiveConditionalCrash4.ts, 2, 16)) +>Length : Symbol(Length, Decl(recursiveConditionalCrash4.ts, 3, 21)) +>StrIter : Symbol(StrIter) +>Prev : Symbol(StrIter.Prev) +>It : Symbol(It, Decl(recursiveConditionalCrash4.ts, 4, 33)) + + : Length; +>Length : Symbol(Length, Decl(recursiveConditionalCrash4.ts, 3, 21)) + +type Foo = T extends unknown +>Foo : Symbol(Foo, Decl(recursiveConditionalCrash4.ts, 10, 11)) +>T : Symbol(T, Decl(recursiveConditionalCrash4.ts, 12, 9)) +>T : Symbol(T, Decl(recursiveConditionalCrash4.ts, 12, 9)) + + ? unknown extends `${infer $Rest}` +>$Rest : Symbol($Rest, Decl(recursiveConditionalCrash4.ts, 13, 28)) + + ? Foo +>Foo : Symbol(Foo, Decl(recursiveConditionalCrash4.ts, 10, 11)) +>T : Symbol(T, Decl(recursiveConditionalCrash4.ts, 12, 9)) + + : Foo +>Foo : Symbol(Foo, Decl(recursiveConditionalCrash4.ts, 10, 11)) + + : unknown; + diff --git a/tests/baselines/reference/recursiveConditionalCrash4.types b/tests/baselines/reference/recursiveConditionalCrash4.types new file mode 100644 index 0000000000000..18cd601ae1f02 --- /dev/null +++ b/tests/baselines/reference/recursiveConditionalCrash4.types @@ -0,0 +1,31 @@ +=== tests/cases/compiler/recursiveConditionalCrash4.ts === +// Repros from #53783 + +type LengthDown< +>LengthDown : LengthDown + + Str extends string, + Length extends number | bigint, + It +> = It extends StrIter.Iterator +>StrIter : any + + ? StrIter.CutAt extends `${infer $Rest}` +>StrIter : any + + ? LengthDown<$Rest, Add>, It> +>StrIter : any + + : LengthDown> +>StrIter : any + + : Length; + +type Foo = T extends unknown +>Foo : Foo + + ? unknown extends `${infer $Rest}` + ? Foo + : Foo + : unknown; + diff --git a/tests/cases/compiler/recursiveConditionalCrash4.ts b/tests/cases/compiler/recursiveConditionalCrash4.ts new file mode 100644 index 0000000000000..9cbe16188edf9 --- /dev/null +++ b/tests/cases/compiler/recursiveConditionalCrash4.ts @@ -0,0 +1,20 @@ +// @strict: true +// @noEmit: true + +// Repros from #53783 + +type LengthDown< + Str extends string, + Length extends number | bigint, + It +> = It extends StrIter.Iterator + ? StrIter.CutAt extends `${infer $Rest}` + ? LengthDown<$Rest, Add>, It> + : LengthDown> + : Length; + +type Foo = T extends unknown + ? unknown extends `${infer $Rest}` + ? Foo + : Foo + : unknown;