Skip to content

Limit tuple size resulting from spread #42448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 2, 2021
Merged
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
9 changes: 8 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13173,8 +13173,15 @@ namespace ts {
addElement(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]);
}
else if (isTupleType(type)) {
const elements = getTypeArguments(type);
if (elements.length + expandedTypes.length >= 10_000) {
error(currentNode, isPartOfTypeNode(currentNode!)
? Diagnostics.Type_produces_a_tuple_type_that_is_too_large_to_represent
: Diagnostics.Expression_produces_a_tuple_type_that_is_too_large_to_represent);
return errorType;
}
// Spread variadic elements with tuple types into the resulting tuple.
forEach(getTypeArguments(type), (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n]));
forEach(elements, (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n]));
}
else {
// Treat everything else as an array type and create a rest element.
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3248,6 +3248,14 @@
"category": "Error",
"code": 2798
},
"Type produces a tuple type that is too large to represent.": {
"category": "Error",
"code": 2799
},
"Expression produces a tuple type that is too large to represent.": {
"category": "Error",
"code": 2800
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
54 changes: 54 additions & 0 deletions tests/baselines/reference/excessivelyLargeTupleSpread.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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) ====
// #41771

type BuildTuple<L extends number, T extends any[] = [any]> =
T['length'] extends L ? T : BuildTuple<L, [...T, ...T]>;

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];
type T1 = [...T0, ...T0];
type T2 = [...T1, ...T1];
type T3 = [...T2, ...T2];
type T4 = [...T3, ...T3];
type T5 = [...T4, ...T4];
type T6 = [...T5, ...T5];
type T7 = [...T6, ...T6];
type T8 = [...T7, ...T7];
type T9 = [...T8, ...T8];
type T10 = [...T9, ...T9];
type T11 = [...T10, ...T10];
type T12 = [...T11, ...T11];
type T13 = [...T12, ...T12];
type T14 = [...T13, ...T13]; // 2^14 > 10,000
~~~~~~~~~~~~~~~~
!!! error TS2799: Type produces a tuple type that is too large to represent.

const a0 = [0] as const;
const a1 = [...a0, ...a0] as const;
const a2 = [...a1, ...a1] as const;
const a3 = [...a2, ...a2] as const;
const a4 = [...a3, ...a3] as const;
const a5 = [...a4, ...a4] as const;
const a6 = [...a5, ...a5] as const;
const a7 = [...a6, ...a6] as const;
const a8 = [...a7, ...a7] as const;
const a9 = [...a8, ...a8] as const;
const a10 = [...a9, ...a9] as const;
const a11 = [...a10, ...a10] as const;
const a12 = [...a11, ...a11] as const;
const a13 = [...a12, ...a12] as const;
const a14 = [...a13, ...a13] as const; // 2^14 > 10,000
~~~~~~~~~~~~~~~~
!!! error TS2800: Expression produces a tuple type that is too large to represent.

63 changes: 63 additions & 0 deletions tests/baselines/reference/excessivelyLargeTupleSpread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//// [excessivelyLargeTupleSpread.ts]
// #41771

type BuildTuple<L extends number, T extends any[] = [any]> =
T['length'] extends L ? T : BuildTuple<L, [...T, ...T]>;

type A = BuildTuple<3>

type T0 = [any];
type T1 = [...T0, ...T0];
type T2 = [...T1, ...T1];
type T3 = [...T2, ...T2];
type T4 = [...T3, ...T3];
type T5 = [...T4, ...T4];
type T6 = [...T5, ...T5];
type T7 = [...T6, ...T6];
type T8 = [...T7, ...T7];
type T9 = [...T8, ...T8];
type T10 = [...T9, ...T9];
type T11 = [...T10, ...T10];
type T12 = [...T11, ...T11];
type T13 = [...T12, ...T12];
type T14 = [...T13, ...T13]; // 2^14 > 10,000

const a0 = [0] as const;
const a1 = [...a0, ...a0] as const;
const a2 = [...a1, ...a1] as const;
const a3 = [...a2, ...a2] as const;
const a4 = [...a3, ...a3] as const;
const a5 = [...a4, ...a4] as const;
const a6 = [...a5, ...a5] as const;
const a7 = [...a6, ...a6] as const;
const a8 = [...a7, ...a7] as const;
const a9 = [...a8, ...a8] as const;
const a10 = [...a9, ...a9] as const;
const a11 = [...a10, ...a10] as const;
const a12 = [...a11, ...a11] as const;
const a13 = [...a12, ...a12] as const;
const a14 = [...a13, ...a13] as const; // 2^14 > 10,000


//// [excessivelyLargeTupleSpread.js]
// #41771
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
var a0 = [0];
var a1 = __spreadArray(__spreadArray([], a0), a0);
var a2 = __spreadArray(__spreadArray([], a1), a1);
var a3 = __spreadArray(__spreadArray([], a2), a2);
var a4 = __spreadArray(__spreadArray([], a3), a3);
var a5 = __spreadArray(__spreadArray([], a4), a4);
var a6 = __spreadArray(__spreadArray([], a5), a5);
var a7 = __spreadArray(__spreadArray([], a6), a6);
var a8 = __spreadArray(__spreadArray([], a7), a7);
var a9 = __spreadArray(__spreadArray([], a8), a8);
var a10 = __spreadArray(__spreadArray([], a9), a9);
var a11 = __spreadArray(__spreadArray([], a10), a10);
var a12 = __spreadArray(__spreadArray([], a11), a11);
var a13 = __spreadArray(__spreadArray([], a12), a12);
var a14 = __spreadArray(__spreadArray([], a13), a13); // 2^14 > 10,000
167 changes: 167 additions & 0 deletions tests/baselines/reference/excessivelyLargeTupleSpread.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
=== tests/cases/compiler/excessivelyLargeTupleSpread.ts ===
// #41771

type BuildTuple<L extends number, T extends any[] = [any]> =
>BuildTuple : Symbol(BuildTuple, Decl(excessivelyLargeTupleSpread.ts, 0, 0))
>L : Symbol(L, Decl(excessivelyLargeTupleSpread.ts, 2, 16))
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))

T['length'] extends L ? T : BuildTuple<L, [...T, ...T]>;
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
>L : Symbol(L, Decl(excessivelyLargeTupleSpread.ts, 2, 16))
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
>BuildTuple : Symbol(BuildTuple, Decl(excessivelyLargeTupleSpread.ts, 0, 0))
>L : Symbol(L, Decl(excessivelyLargeTupleSpread.ts, 2, 16))
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))

type A = BuildTuple<3>
>A : Symbol(A, Decl(excessivelyLargeTupleSpread.ts, 3, 60))
>BuildTuple : Symbol(BuildTuple, Decl(excessivelyLargeTupleSpread.ts, 0, 0))

type T0 = [any];
>T0 : Symbol(T0, Decl(excessivelyLargeTupleSpread.ts, 5, 22))

type T1 = [...T0, ...T0];
>T1 : Symbol(T1, Decl(excessivelyLargeTupleSpread.ts, 7, 16))
>T0 : Symbol(T0, Decl(excessivelyLargeTupleSpread.ts, 5, 22))
>T0 : Symbol(T0, Decl(excessivelyLargeTupleSpread.ts, 5, 22))

type T2 = [...T1, ...T1];
>T2 : Symbol(T2, Decl(excessivelyLargeTupleSpread.ts, 8, 25))
>T1 : Symbol(T1, Decl(excessivelyLargeTupleSpread.ts, 7, 16))
>T1 : Symbol(T1, Decl(excessivelyLargeTupleSpread.ts, 7, 16))

type T3 = [...T2, ...T2];
>T3 : Symbol(T3, Decl(excessivelyLargeTupleSpread.ts, 9, 25))
>T2 : Symbol(T2, Decl(excessivelyLargeTupleSpread.ts, 8, 25))
>T2 : Symbol(T2, Decl(excessivelyLargeTupleSpread.ts, 8, 25))

type T4 = [...T3, ...T3];
>T4 : Symbol(T4, Decl(excessivelyLargeTupleSpread.ts, 10, 25))
>T3 : Symbol(T3, Decl(excessivelyLargeTupleSpread.ts, 9, 25))
>T3 : Symbol(T3, Decl(excessivelyLargeTupleSpread.ts, 9, 25))

type T5 = [...T4, ...T4];
>T5 : Symbol(T5, Decl(excessivelyLargeTupleSpread.ts, 11, 25))
>T4 : Symbol(T4, Decl(excessivelyLargeTupleSpread.ts, 10, 25))
>T4 : Symbol(T4, Decl(excessivelyLargeTupleSpread.ts, 10, 25))

type T6 = [...T5, ...T5];
>T6 : Symbol(T6, Decl(excessivelyLargeTupleSpread.ts, 12, 25))
>T5 : Symbol(T5, Decl(excessivelyLargeTupleSpread.ts, 11, 25))
>T5 : Symbol(T5, Decl(excessivelyLargeTupleSpread.ts, 11, 25))

type T7 = [...T6, ...T6];
>T7 : Symbol(T7, Decl(excessivelyLargeTupleSpread.ts, 13, 25))
>T6 : Symbol(T6, Decl(excessivelyLargeTupleSpread.ts, 12, 25))
>T6 : Symbol(T6, Decl(excessivelyLargeTupleSpread.ts, 12, 25))

type T8 = [...T7, ...T7];
>T8 : Symbol(T8, Decl(excessivelyLargeTupleSpread.ts, 14, 25))
>T7 : Symbol(T7, Decl(excessivelyLargeTupleSpread.ts, 13, 25))
>T7 : Symbol(T7, Decl(excessivelyLargeTupleSpread.ts, 13, 25))

type T9 = [...T8, ...T8];
>T9 : Symbol(T9, Decl(excessivelyLargeTupleSpread.ts, 15, 25))
>T8 : Symbol(T8, Decl(excessivelyLargeTupleSpread.ts, 14, 25))
>T8 : Symbol(T8, Decl(excessivelyLargeTupleSpread.ts, 14, 25))

type T10 = [...T9, ...T9];
>T10 : Symbol(T10, Decl(excessivelyLargeTupleSpread.ts, 16, 25))
>T9 : Symbol(T9, Decl(excessivelyLargeTupleSpread.ts, 15, 25))
>T9 : Symbol(T9, Decl(excessivelyLargeTupleSpread.ts, 15, 25))

type T11 = [...T10, ...T10];
>T11 : Symbol(T11, Decl(excessivelyLargeTupleSpread.ts, 17, 26))
>T10 : Symbol(T10, Decl(excessivelyLargeTupleSpread.ts, 16, 25))
>T10 : Symbol(T10, Decl(excessivelyLargeTupleSpread.ts, 16, 25))

type T12 = [...T11, ...T11];
>T12 : Symbol(T12, Decl(excessivelyLargeTupleSpread.ts, 18, 28))
>T11 : Symbol(T11, Decl(excessivelyLargeTupleSpread.ts, 17, 26))
>T11 : Symbol(T11, Decl(excessivelyLargeTupleSpread.ts, 17, 26))

type T13 = [...T12, ...T12];
>T13 : Symbol(T13, Decl(excessivelyLargeTupleSpread.ts, 19, 28))
>T12 : Symbol(T12, Decl(excessivelyLargeTupleSpread.ts, 18, 28))
>T12 : Symbol(T12, Decl(excessivelyLargeTupleSpread.ts, 18, 28))

type T14 = [...T13, ...T13]; // 2^14 > 10,000
>T14 : Symbol(T14, Decl(excessivelyLargeTupleSpread.ts, 20, 28))
>T13 : Symbol(T13, Decl(excessivelyLargeTupleSpread.ts, 19, 28))
>T13 : Symbol(T13, Decl(excessivelyLargeTupleSpread.ts, 19, 28))

const a0 = [0] as const;
>a0 : Symbol(a0, Decl(excessivelyLargeTupleSpread.ts, 23, 5))

const a1 = [...a0, ...a0] as const;
>a1 : Symbol(a1, Decl(excessivelyLargeTupleSpread.ts, 24, 5))
>a0 : Symbol(a0, Decl(excessivelyLargeTupleSpread.ts, 23, 5))
>a0 : Symbol(a0, Decl(excessivelyLargeTupleSpread.ts, 23, 5))

const a2 = [...a1, ...a1] as const;
>a2 : Symbol(a2, Decl(excessivelyLargeTupleSpread.ts, 25, 5))
>a1 : Symbol(a1, Decl(excessivelyLargeTupleSpread.ts, 24, 5))
>a1 : Symbol(a1, Decl(excessivelyLargeTupleSpread.ts, 24, 5))

const a3 = [...a2, ...a2] as const;
>a3 : Symbol(a3, Decl(excessivelyLargeTupleSpread.ts, 26, 5))
>a2 : Symbol(a2, Decl(excessivelyLargeTupleSpread.ts, 25, 5))
>a2 : Symbol(a2, Decl(excessivelyLargeTupleSpread.ts, 25, 5))

const a4 = [...a3, ...a3] as const;
>a4 : Symbol(a4, Decl(excessivelyLargeTupleSpread.ts, 27, 5))
>a3 : Symbol(a3, Decl(excessivelyLargeTupleSpread.ts, 26, 5))
>a3 : Symbol(a3, Decl(excessivelyLargeTupleSpread.ts, 26, 5))

const a5 = [...a4, ...a4] as const;
>a5 : Symbol(a5, Decl(excessivelyLargeTupleSpread.ts, 28, 5))
>a4 : Symbol(a4, Decl(excessivelyLargeTupleSpread.ts, 27, 5))
>a4 : Symbol(a4, Decl(excessivelyLargeTupleSpread.ts, 27, 5))

const a6 = [...a5, ...a5] as const;
>a6 : Symbol(a6, Decl(excessivelyLargeTupleSpread.ts, 29, 5))
>a5 : Symbol(a5, Decl(excessivelyLargeTupleSpread.ts, 28, 5))
>a5 : Symbol(a5, Decl(excessivelyLargeTupleSpread.ts, 28, 5))

const a7 = [...a6, ...a6] as const;
>a7 : Symbol(a7, Decl(excessivelyLargeTupleSpread.ts, 30, 5))
>a6 : Symbol(a6, Decl(excessivelyLargeTupleSpread.ts, 29, 5))
>a6 : Symbol(a6, Decl(excessivelyLargeTupleSpread.ts, 29, 5))

const a8 = [...a7, ...a7] as const;
>a8 : Symbol(a8, Decl(excessivelyLargeTupleSpread.ts, 31, 5))
>a7 : Symbol(a7, Decl(excessivelyLargeTupleSpread.ts, 30, 5))
>a7 : Symbol(a7, Decl(excessivelyLargeTupleSpread.ts, 30, 5))

const a9 = [...a8, ...a8] as const;
>a9 : Symbol(a9, Decl(excessivelyLargeTupleSpread.ts, 32, 5))
>a8 : Symbol(a8, Decl(excessivelyLargeTupleSpread.ts, 31, 5))
>a8 : Symbol(a8, Decl(excessivelyLargeTupleSpread.ts, 31, 5))

const a10 = [...a9, ...a9] as const;
>a10 : Symbol(a10, Decl(excessivelyLargeTupleSpread.ts, 33, 5))
>a9 : Symbol(a9, Decl(excessivelyLargeTupleSpread.ts, 32, 5))
>a9 : Symbol(a9, Decl(excessivelyLargeTupleSpread.ts, 32, 5))

const a11 = [...a10, ...a10] as const;
>a11 : Symbol(a11, Decl(excessivelyLargeTupleSpread.ts, 34, 5))
>a10 : Symbol(a10, Decl(excessivelyLargeTupleSpread.ts, 33, 5))
>a10 : Symbol(a10, Decl(excessivelyLargeTupleSpread.ts, 33, 5))

const a12 = [...a11, ...a11] as const;
>a12 : Symbol(a12, Decl(excessivelyLargeTupleSpread.ts, 35, 5))
>a11 : Symbol(a11, Decl(excessivelyLargeTupleSpread.ts, 34, 5))
>a11 : Symbol(a11, Decl(excessivelyLargeTupleSpread.ts, 34, 5))

const a13 = [...a12, ...a12] as const;
>a13 : Symbol(a13, Decl(excessivelyLargeTupleSpread.ts, 36, 5))
>a12 : Symbol(a12, Decl(excessivelyLargeTupleSpread.ts, 35, 5))
>a12 : Symbol(a12, Decl(excessivelyLargeTupleSpread.ts, 35, 5))

const a14 = [...a13, ...a13] as const; // 2^14 > 10,000
>a14 : Symbol(a14, Decl(excessivelyLargeTupleSpread.ts, 37, 5))
>a13 : Symbol(a13, Decl(excessivelyLargeTupleSpread.ts, 36, 5))
>a13 : Symbol(a13, Decl(excessivelyLargeTupleSpread.ts, 36, 5))

Loading