Skip to content

Commit 71de94a

Browse files
authored
Limit tuple size resulting from spread (#42448)
* Limit tuple size resulting from spread * Update limit to 10k * Update baseline after merge conflict
1 parent fd6178b commit 71de94a

File tree

7 files changed

+526
-1
lines changed

7 files changed

+526
-1
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13173,8 +13173,15 @@ namespace ts {
1317313173
addElement(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]);
1317413174
}
1317513175
else if (isTupleType(type)) {
13176+
const elements = getTypeArguments(type);
13177+
if (elements.length + expandedTypes.length >= 10_000) {
13178+
error(currentNode, isPartOfTypeNode(currentNode!)
13179+
? Diagnostics.Type_produces_a_tuple_type_that_is_too_large_to_represent
13180+
: Diagnostics.Expression_produces_a_tuple_type_that_is_too_large_to_represent);
13181+
return errorType;
13182+
}
1317613183
// Spread variadic elements with tuple types into the resulting tuple.
13177-
forEach(getTypeArguments(type), (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n]));
13184+
forEach(elements, (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n]));
1317813185
}
1317913186
else {
1318013187
// Treat everything else as an array type and create a rest element.

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,6 +3248,14 @@
32483248
"category": "Error",
32493249
"code": 2798
32503250
},
3251+
"Type produces a tuple type that is too large to represent.": {
3252+
"category": "Error",
3253+
"code": 2799
3254+
},
3255+
"Expression produces a tuple type that is too large to represent.": {
3256+
"category": "Error",
3257+
"code": 2800
3258+
},
32513259

32523260
"Import declaration '{0}' is using private name '{1}'.": {
32533261
"category": "Error",
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
tests/cases/compiler/excessivelyLargeTupleSpread.ts(6,10): error TS2589: Type instantiation is excessively deep and possibly infinite.
2+
tests/cases/compiler/excessivelyLargeTupleSpread.ts(6,10): error TS2799: Type produces a tuple type that is too large to represent.
3+
tests/cases/compiler/excessivelyLargeTupleSpread.ts(22,12): error TS2799: Type produces a tuple type that is too large to represent.
4+
tests/cases/compiler/excessivelyLargeTupleSpread.ts(38,13): error TS2800: Expression produces a tuple type that is too large to represent.
5+
6+
7+
==== tests/cases/compiler/excessivelyLargeTupleSpread.ts (4 errors) ====
8+
// #41771
9+
10+
type BuildTuple<L extends number, T extends any[] = [any]> =
11+
T['length'] extends L ? T : BuildTuple<L, [...T, ...T]>;
12+
13+
type A = BuildTuple<3>
14+
~~~~~~~~~~~~~
15+
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
16+
~~~~~~~~~~~~~
17+
!!! error TS2799: Type produces a tuple type that is too large to represent.
18+
19+
type T0 = [any];
20+
type T1 = [...T0, ...T0];
21+
type T2 = [...T1, ...T1];
22+
type T3 = [...T2, ...T2];
23+
type T4 = [...T3, ...T3];
24+
type T5 = [...T4, ...T4];
25+
type T6 = [...T5, ...T5];
26+
type T7 = [...T6, ...T6];
27+
type T8 = [...T7, ...T7];
28+
type T9 = [...T8, ...T8];
29+
type T10 = [...T9, ...T9];
30+
type T11 = [...T10, ...T10];
31+
type T12 = [...T11, ...T11];
32+
type T13 = [...T12, ...T12];
33+
type T14 = [...T13, ...T13]; // 2^14 > 10,000
34+
~~~~~~~~~~~~~~~~
35+
!!! error TS2799: Type produces a tuple type that is too large to represent.
36+
37+
const a0 = [0] as const;
38+
const a1 = [...a0, ...a0] as const;
39+
const a2 = [...a1, ...a1] as const;
40+
const a3 = [...a2, ...a2] as const;
41+
const a4 = [...a3, ...a3] as const;
42+
const a5 = [...a4, ...a4] as const;
43+
const a6 = [...a5, ...a5] as const;
44+
const a7 = [...a6, ...a6] as const;
45+
const a8 = [...a7, ...a7] as const;
46+
const a9 = [...a8, ...a8] as const;
47+
const a10 = [...a9, ...a9] as const;
48+
const a11 = [...a10, ...a10] as const;
49+
const a12 = [...a11, ...a11] as const;
50+
const a13 = [...a12, ...a12] as const;
51+
const a14 = [...a13, ...a13] as const; // 2^14 > 10,000
52+
~~~~~~~~~~~~~~~~
53+
!!! error TS2800: Expression produces a tuple type that is too large to represent.
54+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//// [excessivelyLargeTupleSpread.ts]
2+
// #41771
3+
4+
type BuildTuple<L extends number, T extends any[] = [any]> =
5+
T['length'] extends L ? T : BuildTuple<L, [...T, ...T]>;
6+
7+
type A = BuildTuple<3>
8+
9+
type T0 = [any];
10+
type T1 = [...T0, ...T0];
11+
type T2 = [...T1, ...T1];
12+
type T3 = [...T2, ...T2];
13+
type T4 = [...T3, ...T3];
14+
type T5 = [...T4, ...T4];
15+
type T6 = [...T5, ...T5];
16+
type T7 = [...T6, ...T6];
17+
type T8 = [...T7, ...T7];
18+
type T9 = [...T8, ...T8];
19+
type T10 = [...T9, ...T9];
20+
type T11 = [...T10, ...T10];
21+
type T12 = [...T11, ...T11];
22+
type T13 = [...T12, ...T12];
23+
type T14 = [...T13, ...T13]; // 2^14 > 10,000
24+
25+
const a0 = [0] as const;
26+
const a1 = [...a0, ...a0] as const;
27+
const a2 = [...a1, ...a1] as const;
28+
const a3 = [...a2, ...a2] as const;
29+
const a4 = [...a3, ...a3] as const;
30+
const a5 = [...a4, ...a4] as const;
31+
const a6 = [...a5, ...a5] as const;
32+
const a7 = [...a6, ...a6] as const;
33+
const a8 = [...a7, ...a7] as const;
34+
const a9 = [...a8, ...a8] as const;
35+
const a10 = [...a9, ...a9] as const;
36+
const a11 = [...a10, ...a10] as const;
37+
const a12 = [...a11, ...a11] as const;
38+
const a13 = [...a12, ...a12] as const;
39+
const a14 = [...a13, ...a13] as const; // 2^14 > 10,000
40+
41+
42+
//// [excessivelyLargeTupleSpread.js]
43+
// #41771
44+
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
45+
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
46+
to[j] = from[i];
47+
return to;
48+
};
49+
var a0 = [0];
50+
var a1 = __spreadArray(__spreadArray([], a0), a0);
51+
var a2 = __spreadArray(__spreadArray([], a1), a1);
52+
var a3 = __spreadArray(__spreadArray([], a2), a2);
53+
var a4 = __spreadArray(__spreadArray([], a3), a3);
54+
var a5 = __spreadArray(__spreadArray([], a4), a4);
55+
var a6 = __spreadArray(__spreadArray([], a5), a5);
56+
var a7 = __spreadArray(__spreadArray([], a6), a6);
57+
var a8 = __spreadArray(__spreadArray([], a7), a7);
58+
var a9 = __spreadArray(__spreadArray([], a8), a8);
59+
var a10 = __spreadArray(__spreadArray([], a9), a9);
60+
var a11 = __spreadArray(__spreadArray([], a10), a10);
61+
var a12 = __spreadArray(__spreadArray([], a11), a11);
62+
var a13 = __spreadArray(__spreadArray([], a12), a12);
63+
var a14 = __spreadArray(__spreadArray([], a13), a13); // 2^14 > 10,000
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
=== tests/cases/compiler/excessivelyLargeTupleSpread.ts ===
2+
// #41771
3+
4+
type BuildTuple<L extends number, T extends any[] = [any]> =
5+
>BuildTuple : Symbol(BuildTuple, Decl(excessivelyLargeTupleSpread.ts, 0, 0))
6+
>L : Symbol(L, Decl(excessivelyLargeTupleSpread.ts, 2, 16))
7+
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
8+
9+
T['length'] extends L ? T : BuildTuple<L, [...T, ...T]>;
10+
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
11+
>L : Symbol(L, Decl(excessivelyLargeTupleSpread.ts, 2, 16))
12+
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
13+
>BuildTuple : Symbol(BuildTuple, Decl(excessivelyLargeTupleSpread.ts, 0, 0))
14+
>L : Symbol(L, Decl(excessivelyLargeTupleSpread.ts, 2, 16))
15+
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
16+
>T : Symbol(T, Decl(excessivelyLargeTupleSpread.ts, 2, 33))
17+
18+
type A = BuildTuple<3>
19+
>A : Symbol(A, Decl(excessivelyLargeTupleSpread.ts, 3, 60))
20+
>BuildTuple : Symbol(BuildTuple, Decl(excessivelyLargeTupleSpread.ts, 0, 0))
21+
22+
type T0 = [any];
23+
>T0 : Symbol(T0, Decl(excessivelyLargeTupleSpread.ts, 5, 22))
24+
25+
type T1 = [...T0, ...T0];
26+
>T1 : Symbol(T1, Decl(excessivelyLargeTupleSpread.ts, 7, 16))
27+
>T0 : Symbol(T0, Decl(excessivelyLargeTupleSpread.ts, 5, 22))
28+
>T0 : Symbol(T0, Decl(excessivelyLargeTupleSpread.ts, 5, 22))
29+
30+
type T2 = [...T1, ...T1];
31+
>T2 : Symbol(T2, Decl(excessivelyLargeTupleSpread.ts, 8, 25))
32+
>T1 : Symbol(T1, Decl(excessivelyLargeTupleSpread.ts, 7, 16))
33+
>T1 : Symbol(T1, Decl(excessivelyLargeTupleSpread.ts, 7, 16))
34+
35+
type T3 = [...T2, ...T2];
36+
>T3 : Symbol(T3, Decl(excessivelyLargeTupleSpread.ts, 9, 25))
37+
>T2 : Symbol(T2, Decl(excessivelyLargeTupleSpread.ts, 8, 25))
38+
>T2 : Symbol(T2, Decl(excessivelyLargeTupleSpread.ts, 8, 25))
39+
40+
type T4 = [...T3, ...T3];
41+
>T4 : Symbol(T4, Decl(excessivelyLargeTupleSpread.ts, 10, 25))
42+
>T3 : Symbol(T3, Decl(excessivelyLargeTupleSpread.ts, 9, 25))
43+
>T3 : Symbol(T3, Decl(excessivelyLargeTupleSpread.ts, 9, 25))
44+
45+
type T5 = [...T4, ...T4];
46+
>T5 : Symbol(T5, Decl(excessivelyLargeTupleSpread.ts, 11, 25))
47+
>T4 : Symbol(T4, Decl(excessivelyLargeTupleSpread.ts, 10, 25))
48+
>T4 : Symbol(T4, Decl(excessivelyLargeTupleSpread.ts, 10, 25))
49+
50+
type T6 = [...T5, ...T5];
51+
>T6 : Symbol(T6, Decl(excessivelyLargeTupleSpread.ts, 12, 25))
52+
>T5 : Symbol(T5, Decl(excessivelyLargeTupleSpread.ts, 11, 25))
53+
>T5 : Symbol(T5, Decl(excessivelyLargeTupleSpread.ts, 11, 25))
54+
55+
type T7 = [...T6, ...T6];
56+
>T7 : Symbol(T7, Decl(excessivelyLargeTupleSpread.ts, 13, 25))
57+
>T6 : Symbol(T6, Decl(excessivelyLargeTupleSpread.ts, 12, 25))
58+
>T6 : Symbol(T6, Decl(excessivelyLargeTupleSpread.ts, 12, 25))
59+
60+
type T8 = [...T7, ...T7];
61+
>T8 : Symbol(T8, Decl(excessivelyLargeTupleSpread.ts, 14, 25))
62+
>T7 : Symbol(T7, Decl(excessivelyLargeTupleSpread.ts, 13, 25))
63+
>T7 : Symbol(T7, Decl(excessivelyLargeTupleSpread.ts, 13, 25))
64+
65+
type T9 = [...T8, ...T8];
66+
>T9 : Symbol(T9, Decl(excessivelyLargeTupleSpread.ts, 15, 25))
67+
>T8 : Symbol(T8, Decl(excessivelyLargeTupleSpread.ts, 14, 25))
68+
>T8 : Symbol(T8, Decl(excessivelyLargeTupleSpread.ts, 14, 25))
69+
70+
type T10 = [...T9, ...T9];
71+
>T10 : Symbol(T10, Decl(excessivelyLargeTupleSpread.ts, 16, 25))
72+
>T9 : Symbol(T9, Decl(excessivelyLargeTupleSpread.ts, 15, 25))
73+
>T9 : Symbol(T9, Decl(excessivelyLargeTupleSpread.ts, 15, 25))
74+
75+
type T11 = [...T10, ...T10];
76+
>T11 : Symbol(T11, Decl(excessivelyLargeTupleSpread.ts, 17, 26))
77+
>T10 : Symbol(T10, Decl(excessivelyLargeTupleSpread.ts, 16, 25))
78+
>T10 : Symbol(T10, Decl(excessivelyLargeTupleSpread.ts, 16, 25))
79+
80+
type T12 = [...T11, ...T11];
81+
>T12 : Symbol(T12, Decl(excessivelyLargeTupleSpread.ts, 18, 28))
82+
>T11 : Symbol(T11, Decl(excessivelyLargeTupleSpread.ts, 17, 26))
83+
>T11 : Symbol(T11, Decl(excessivelyLargeTupleSpread.ts, 17, 26))
84+
85+
type T13 = [...T12, ...T12];
86+
>T13 : Symbol(T13, Decl(excessivelyLargeTupleSpread.ts, 19, 28))
87+
>T12 : Symbol(T12, Decl(excessivelyLargeTupleSpread.ts, 18, 28))
88+
>T12 : Symbol(T12, Decl(excessivelyLargeTupleSpread.ts, 18, 28))
89+
90+
type T14 = [...T13, ...T13]; // 2^14 > 10,000
91+
>T14 : Symbol(T14, Decl(excessivelyLargeTupleSpread.ts, 20, 28))
92+
>T13 : Symbol(T13, Decl(excessivelyLargeTupleSpread.ts, 19, 28))
93+
>T13 : Symbol(T13, Decl(excessivelyLargeTupleSpread.ts, 19, 28))
94+
95+
const a0 = [0] as const;
96+
>a0 : Symbol(a0, Decl(excessivelyLargeTupleSpread.ts, 23, 5))
97+
98+
const a1 = [...a0, ...a0] as const;
99+
>a1 : Symbol(a1, Decl(excessivelyLargeTupleSpread.ts, 24, 5))
100+
>a0 : Symbol(a0, Decl(excessivelyLargeTupleSpread.ts, 23, 5))
101+
>a0 : Symbol(a0, Decl(excessivelyLargeTupleSpread.ts, 23, 5))
102+
103+
const a2 = [...a1, ...a1] as const;
104+
>a2 : Symbol(a2, Decl(excessivelyLargeTupleSpread.ts, 25, 5))
105+
>a1 : Symbol(a1, Decl(excessivelyLargeTupleSpread.ts, 24, 5))
106+
>a1 : Symbol(a1, Decl(excessivelyLargeTupleSpread.ts, 24, 5))
107+
108+
const a3 = [...a2, ...a2] as const;
109+
>a3 : Symbol(a3, Decl(excessivelyLargeTupleSpread.ts, 26, 5))
110+
>a2 : Symbol(a2, Decl(excessivelyLargeTupleSpread.ts, 25, 5))
111+
>a2 : Symbol(a2, Decl(excessivelyLargeTupleSpread.ts, 25, 5))
112+
113+
const a4 = [...a3, ...a3] as const;
114+
>a4 : Symbol(a4, Decl(excessivelyLargeTupleSpread.ts, 27, 5))
115+
>a3 : Symbol(a3, Decl(excessivelyLargeTupleSpread.ts, 26, 5))
116+
>a3 : Symbol(a3, Decl(excessivelyLargeTupleSpread.ts, 26, 5))
117+
118+
const a5 = [...a4, ...a4] as const;
119+
>a5 : Symbol(a5, Decl(excessivelyLargeTupleSpread.ts, 28, 5))
120+
>a4 : Symbol(a4, Decl(excessivelyLargeTupleSpread.ts, 27, 5))
121+
>a4 : Symbol(a4, Decl(excessivelyLargeTupleSpread.ts, 27, 5))
122+
123+
const a6 = [...a5, ...a5] as const;
124+
>a6 : Symbol(a6, Decl(excessivelyLargeTupleSpread.ts, 29, 5))
125+
>a5 : Symbol(a5, Decl(excessivelyLargeTupleSpread.ts, 28, 5))
126+
>a5 : Symbol(a5, Decl(excessivelyLargeTupleSpread.ts, 28, 5))
127+
128+
const a7 = [...a6, ...a6] as const;
129+
>a7 : Symbol(a7, Decl(excessivelyLargeTupleSpread.ts, 30, 5))
130+
>a6 : Symbol(a6, Decl(excessivelyLargeTupleSpread.ts, 29, 5))
131+
>a6 : Symbol(a6, Decl(excessivelyLargeTupleSpread.ts, 29, 5))
132+
133+
const a8 = [...a7, ...a7] as const;
134+
>a8 : Symbol(a8, Decl(excessivelyLargeTupleSpread.ts, 31, 5))
135+
>a7 : Symbol(a7, Decl(excessivelyLargeTupleSpread.ts, 30, 5))
136+
>a7 : Symbol(a7, Decl(excessivelyLargeTupleSpread.ts, 30, 5))
137+
138+
const a9 = [...a8, ...a8] as const;
139+
>a9 : Symbol(a9, Decl(excessivelyLargeTupleSpread.ts, 32, 5))
140+
>a8 : Symbol(a8, Decl(excessivelyLargeTupleSpread.ts, 31, 5))
141+
>a8 : Symbol(a8, Decl(excessivelyLargeTupleSpread.ts, 31, 5))
142+
143+
const a10 = [...a9, ...a9] as const;
144+
>a10 : Symbol(a10, Decl(excessivelyLargeTupleSpread.ts, 33, 5))
145+
>a9 : Symbol(a9, Decl(excessivelyLargeTupleSpread.ts, 32, 5))
146+
>a9 : Symbol(a9, Decl(excessivelyLargeTupleSpread.ts, 32, 5))
147+
148+
const a11 = [...a10, ...a10] as const;
149+
>a11 : Symbol(a11, Decl(excessivelyLargeTupleSpread.ts, 34, 5))
150+
>a10 : Symbol(a10, Decl(excessivelyLargeTupleSpread.ts, 33, 5))
151+
>a10 : Symbol(a10, Decl(excessivelyLargeTupleSpread.ts, 33, 5))
152+
153+
const a12 = [...a11, ...a11] as const;
154+
>a12 : Symbol(a12, Decl(excessivelyLargeTupleSpread.ts, 35, 5))
155+
>a11 : Symbol(a11, Decl(excessivelyLargeTupleSpread.ts, 34, 5))
156+
>a11 : Symbol(a11, Decl(excessivelyLargeTupleSpread.ts, 34, 5))
157+
158+
const a13 = [...a12, ...a12] as const;
159+
>a13 : Symbol(a13, Decl(excessivelyLargeTupleSpread.ts, 36, 5))
160+
>a12 : Symbol(a12, Decl(excessivelyLargeTupleSpread.ts, 35, 5))
161+
>a12 : Symbol(a12, Decl(excessivelyLargeTupleSpread.ts, 35, 5))
162+
163+
const a14 = [...a13, ...a13] as const; // 2^14 > 10,000
164+
>a14 : Symbol(a14, Decl(excessivelyLargeTupleSpread.ts, 37, 5))
165+
>a13 : Symbol(a13, Decl(excessivelyLargeTupleSpread.ts, 36, 5))
166+
>a13 : Symbol(a13, Decl(excessivelyLargeTupleSpread.ts, 36, 5))
167+

0 commit comments

Comments
 (0)