Propagate errorType in getConditionalType (#53801)

This commit is contained in:
Anders Hejlsberg 2023-04-16 16:15:55 -07:00 committed by GitHub
parent 5897d7a135
commit f8b3ea7972
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 168 additions and 11 deletions

View File

@ -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

View File

@ -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<L extends number, T extends any[] = [any]> =
@ -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];

View File

@ -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<Str, It> extends `${infer $Rest}`
~~~~~~~
!!! error TS2503: Cannot find namespace 'StrIter'.
? LengthDown<$Rest, Add<Length, StrIter.Value<It>>, It>
~~~
!!! error TS2304: Cannot find name 'Add'.
~~~~~~~
!!! error TS2503: Cannot find namespace 'StrIter'.
: LengthDown<Str, Length, StrIter.Prev<It>>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
~~~~~~~
!!! error TS2503: Cannot find namespace 'StrIter'.
: Length;
type Foo<T> = T extends unknown
? unknown extends `${infer $Rest}`
? Foo<T>
: Foo<unknown>
~~~~~~~~~~~~
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
: unknown;

View File

@ -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<Str, It> 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<Length, StrIter.Value<It>>, 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<Str, Length, StrIter.Prev<It>>
>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> = 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<T>
>Foo : Symbol(Foo, Decl(recursiveConditionalCrash4.ts, 10, 11))
>T : Symbol(T, Decl(recursiveConditionalCrash4.ts, 12, 9))
: Foo<unknown>
>Foo : Symbol(Foo, Decl(recursiveConditionalCrash4.ts, 10, 11))
: unknown;

View File

@ -0,0 +1,31 @@
=== tests/cases/compiler/recursiveConditionalCrash4.ts ===
// Repros from #53783
type LengthDown<
>LengthDown : LengthDown<Str, Length, It>
Str extends string,
Length extends number | bigint,
It
> = It extends StrIter.Iterator
>StrIter : any
? StrIter.CutAt<Str, It> extends `${infer $Rest}`
>StrIter : any
? LengthDown<$Rest, Add<Length, StrIter.Value<It>>, It>
>StrIter : any
: LengthDown<Str, Length, StrIter.Prev<It>>
>StrIter : any
: Length;
type Foo<T> = T extends unknown
>Foo : Foo<T>
? unknown extends `${infer $Rest}`
? Foo<T>
: Foo<unknown>
: unknown;

View File

@ -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<Str, It> extends `${infer $Rest}`
? LengthDown<$Rest, Add<Length, StrIter.Value<It>>, It>
: LengthDown<Str, Length, StrIter.Prev<It>>
: Length;
type Foo<T> = T extends unknown
? unknown extends `${infer $Rest}`
? Foo<T>
: Foo<unknown>
: unknown;