Skip to content

Commit 3511123

Browse files
authored
Merge pull request microsoft#40755 from amcasey/SpreadLimit
Enforce a size limit in getSpreadType
2 parents 070cf11 + 9f5310f commit 3511123

6 files changed

+964
-2
lines changed

src/compiler/checker.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -13404,6 +13404,7 @@ namespace ts {
1340413404
function checkCrossProductUnion(types: readonly Type[]) {
1340513405
const size = reduceLeft(types, (n, t) => n * (t.flags & TypeFlags.Union ? (<UnionType>t).types.length : t.flags & TypeFlags.Never ? 0 : 1), 1);
1340613406
if (size >= 100000) {
13407+
tracing.instant(tracing.Phase.Check, "checkCrossProductUnion_DepthLimit", { typeIds: types.map(t => t.id), size });
1340713408
error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
1340813409
return false;
1340913410
}
@@ -14468,14 +14469,18 @@ namespace ts {
1446814469
if (merged) {
1446914470
return getSpreadType(merged, right, symbol, objectFlags, readonly);
1447014471
}
14471-
return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly));
14472+
return checkCrossProductUnion([left, right])
14473+
? mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly))
14474+
: errorType;
1447214475
}
1447314476
if (right.flags & TypeFlags.Union) {
1447414477
const merged = tryMergeUnionOfObjectTypeAndEmptyObject(right as UnionType, readonly);
1447514478
if (merged) {
1447614479
return getSpreadType(left, merged, symbol, objectFlags, readonly);
1447714480
}
14478-
return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly));
14481+
return checkCrossProductUnion([left, right])
14482+
? mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly))
14483+
: errorType;
1447914484
}
1448014485
if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) {
1448114486
return left;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
tests/cases/conformance/types/spread/objectSpreadRepeatedComplexity.ts(3,12): error TS2590: Expression produces a union type that is too complex to represent.
2+
3+
4+
==== tests/cases/conformance/types/spread/objectSpreadRepeatedComplexity.ts (1 errors) ====
5+
function f(cnd: Record<number, boolean>){
6+
// Type is a union of 2^(n-1) members, where n is the number of spread objects
7+
return {
8+
~
9+
// Without this one, it collapses to {} ?
10+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
...(cnd[1] &&
12+
~~~~~~~~~~~~~~~~~~~~~
13+
cnd[2] && {
14+
~~~~~~~~~~~~~~~~~~~~~~~
15+
prop0: 0,
16+
~~~~~~~~~~~~~~~~~~~~~
17+
}),
18+
~~~~~~~~~~~
19+
20+
21+
// With one prop each, it collapses to a single object (#34853?)
22+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23+
...(cnd[3] && {
24+
~~~~~~~~~~~~~~~~~~~~~~~
25+
prop3a: 1,
26+
~~~~~~~~~~~~~~~~~~~~~~
27+
prop3b: 1,
28+
~~~~~~~~~~~~~~~~~~~~~~
29+
}),
30+
~~~~~~~~~~~
31+
...(cnd[4] && {
32+
~~~~~~~~~~~~~~~~~~~~~~~
33+
prop4a: 1,
34+
~~~~~~~~~~~~~~~~~~~~~~
35+
prop4b: 1,
36+
~~~~~~~~~~~~~~~~~~~~~~
37+
}),
38+
~~~~~~~~~~~
39+
...(cnd[5] && {
40+
~~~~~~~~~~~~~~~~~~~~~~~
41+
prop5a: 1,
42+
~~~~~~~~~~~~~~~~~~~~~~
43+
prop5b: 1,
44+
~~~~~~~~~~~~~~~~~~~~~~
45+
}),
46+
~~~~~~~~~~~
47+
...(cnd[6] && {
48+
~~~~~~~~~~~~~~~~~~~~~~~
49+
prop6a: 1,
50+
~~~~~~~~~~~~~~~~~~~~~~
51+
prop6b: 1,
52+
~~~~~~~~~~~~~~~~~~~~~~
53+
}),
54+
~~~~~~~~~~~
55+
...(cnd[7] && {
56+
~~~~~~~~~~~~~~~~~~~~~~~
57+
prop7a: 1,
58+
~~~~~~~~~~~~~~~~~~~~~~
59+
prop7b: 1,
60+
~~~~~~~~~~~~~~~~~~~~~~
61+
}),
62+
~~~~~~~~~~~
63+
...(cnd[8] && {
64+
~~~~~~~~~~~~~~~~~~~~~~~
65+
prop8a: 1,
66+
~~~~~~~~~~~~~~~~~~~~~~
67+
prop8b: 1,
68+
~~~~~~~~~~~~~~~~~~~~~~
69+
}),
70+
~~~~~~~~~~~
71+
...(cnd[9] && {
72+
~~~~~~~~~~~~~~~~~~~~~~~
73+
prop9a: 1,
74+
~~~~~~~~~~~~~~~~~~~~~~
75+
prop9b: 1,
76+
~~~~~~~~~~~~~~~~~~~~~~
77+
}),
78+
~~~~~~~~~~~
79+
...(cnd[10] && {
80+
~~~~~~~~~~~~~~~~~~~~~~~~
81+
prop10a: 1,
82+
~~~~~~~~~~~~~~~~~~~~~~~
83+
prop10b: 1,
84+
~~~~~~~~~~~~~~~~~~~~~~~
85+
}),
86+
~~~~~~~~~~~
87+
...(cnd[11] && {
88+
~~~~~~~~~~~~~~~~~~~~~~~~
89+
prop11a: 1,
90+
~~~~~~~~~~~~~~~~~~~~~~~
91+
prop11b: 1,
92+
~~~~~~~~~~~~~~~~~~~~~~~
93+
}),
94+
~~~~~~~~~~~
95+
...(cnd[12] && {
96+
~~~~~~~~~~~~~~~~~~~~~~~~
97+
prop12a: 1,
98+
~~~~~~~~~~~~~~~~~~~~~~~
99+
prop12b: 1,
100+
~~~~~~~~~~~~~~~~~~~~~~~
101+
}),
102+
~~~~~~~~~~~
103+
...(cnd[13] && {
104+
~~~~~~~~~~~~~~~~~~~~~~~~
105+
prop13a: 1,
106+
~~~~~~~~~~~~~~~~~~~~~~~
107+
prop13b: 1,
108+
~~~~~~~~~~~~~~~~~~~~~~~
109+
}),
110+
~~~~~~~~~~~
111+
...(cnd[14] && {
112+
~~~~~~~~~~~~~~~~~~~~~~~~
113+
prop14a: 1,
114+
~~~~~~~~~~~~~~~~~~~~~~~
115+
prop14b: 1,
116+
~~~~~~~~~~~~~~~~~~~~~~~
117+
}),
118+
~~~~~~~~~~~
119+
...(cnd[15] && {
120+
~~~~~~~~~~~~~~~~~~~~~~~~
121+
prop15a: 1,
122+
~~~~~~~~~~~~~~~~~~~~~~~
123+
prop15b: 1,
124+
~~~~~~~~~~~~~~~~~~~~~~~
125+
}),
126+
~~~~~~~~~~~
127+
...(cnd[16] && {
128+
~~~~~~~~~~~~~~~~~~~~~~~~
129+
prop16a: 1,
130+
~~~~~~~~~~~~~~~~~~~~~~~
131+
prop16b: 1,
132+
~~~~~~~~~~~~~~~~~~~~~~~
133+
}),
134+
~~~~~~~~~~~
135+
...(cnd[17] && {
136+
~~~~~~~~~~~~~~~~~~~~~~~~
137+
prop17a: 1,
138+
~~~~~~~~~~~~~~~~~~~~~~~
139+
prop17b: 1,
140+
~~~~~~~~~~~~~~~~~~~~~~~
141+
}),
142+
~~~~~~~~~~~
143+
...(cnd[18] && {
144+
~~~~~~~~~~~~~~~~~~~~~~~~
145+
prop18a: 1,
146+
~~~~~~~~~~~~~~~~~~~~~~~
147+
prop18b: 1,
148+
~~~~~~~~~~~~~~~~~~~~~~~
149+
}),
150+
~~~~~~~~~~~
151+
...(cnd[19] && {
152+
~~~~~~~~~~~~~~~~~~~~~~~~
153+
prop19a: 1,
154+
~~~~~~~~~~~~~~~~~~~~~~~
155+
prop19b: 1,
156+
~~~~~~~~~~~~~~~~~~~~~~~
157+
}),
158+
~~~~~~~~~~~
159+
...(cnd[20] && {
160+
~~~~~~~~~~~~~~~~~~~~~~~~
161+
prop20a: 1,
162+
~~~~~~~~~~~~~~~~~~~~~~~
163+
prop20b: 1,
164+
~~~~~~~~~~~~~~~~~~~~~~~
165+
}),
166+
~~~~~~~~~~~
167+
};
168+
~~~~~
169+
!!! error TS2590: Expression produces a union type that is too complex to represent.
170+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//// [objectSpreadRepeatedComplexity.ts]
2+
function f(cnd: Record<number, boolean>){
3+
// Type is a union of 2^(n-1) members, where n is the number of spread objects
4+
return {
5+
// Without this one, it collapses to {} ?
6+
...(cnd[1] &&
7+
cnd[2] && {
8+
prop0: 0,
9+
}),
10+
11+
// With one prop each, it collapses to a single object (#34853?)
12+
...(cnd[3] && {
13+
prop3a: 1,
14+
prop3b: 1,
15+
}),
16+
...(cnd[4] && {
17+
prop4a: 1,
18+
prop4b: 1,
19+
}),
20+
...(cnd[5] && {
21+
prop5a: 1,
22+
prop5b: 1,
23+
}),
24+
...(cnd[6] && {
25+
prop6a: 1,
26+
prop6b: 1,
27+
}),
28+
...(cnd[7] && {
29+
prop7a: 1,
30+
prop7b: 1,
31+
}),
32+
...(cnd[8] && {
33+
prop8a: 1,
34+
prop8b: 1,
35+
}),
36+
...(cnd[9] && {
37+
prop9a: 1,
38+
prop9b: 1,
39+
}),
40+
...(cnd[10] && {
41+
prop10a: 1,
42+
prop10b: 1,
43+
}),
44+
...(cnd[11] && {
45+
prop11a: 1,
46+
prop11b: 1,
47+
}),
48+
...(cnd[12] && {
49+
prop12a: 1,
50+
prop12b: 1,
51+
}),
52+
...(cnd[13] && {
53+
prop13a: 1,
54+
prop13b: 1,
55+
}),
56+
...(cnd[14] && {
57+
prop14a: 1,
58+
prop14b: 1,
59+
}),
60+
...(cnd[15] && {
61+
prop15a: 1,
62+
prop15b: 1,
63+
}),
64+
...(cnd[16] && {
65+
prop16a: 1,
66+
prop16b: 1,
67+
}),
68+
...(cnd[17] && {
69+
prop17a: 1,
70+
prop17b: 1,
71+
}),
72+
...(cnd[18] && {
73+
prop18a: 1,
74+
prop18b: 1,
75+
}),
76+
...(cnd[19] && {
77+
prop19a: 1,
78+
prop19b: 1,
79+
}),
80+
...(cnd[20] && {
81+
prop20a: 1,
82+
prop20b: 1,
83+
}),
84+
};
85+
}
86+
87+
//// [objectSpreadRepeatedComplexity.js]
88+
"use strict";
89+
var __assign = (this && this.__assign) || function () {
90+
__assign = Object.assign || function(t) {
91+
for (var s, i = 1, n = arguments.length; i < n; i++) {
92+
s = arguments[i];
93+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
94+
t[p] = s[p];
95+
}
96+
return t;
97+
};
98+
return __assign.apply(this, arguments);
99+
};
100+
function f(cnd) {
101+
// Type is a union of 2^(n-1) members, where n is the number of spread objects
102+
return __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, (cnd[1] &&
103+
cnd[2] && {
104+
prop0: 0
105+
})), (cnd[3] && {
106+
prop3a: 1,
107+
prop3b: 1
108+
})), (cnd[4] && {
109+
prop4a: 1,
110+
prop4b: 1
111+
})), (cnd[5] && {
112+
prop5a: 1,
113+
prop5b: 1
114+
})), (cnd[6] && {
115+
prop6a: 1,
116+
prop6b: 1
117+
})), (cnd[7] && {
118+
prop7a: 1,
119+
prop7b: 1
120+
})), (cnd[8] && {
121+
prop8a: 1,
122+
prop8b: 1
123+
})), (cnd[9] && {
124+
prop9a: 1,
125+
prop9b: 1
126+
})), (cnd[10] && {
127+
prop10a: 1,
128+
prop10b: 1
129+
})), (cnd[11] && {
130+
prop11a: 1,
131+
prop11b: 1
132+
})), (cnd[12] && {
133+
prop12a: 1,
134+
prop12b: 1
135+
})), (cnd[13] && {
136+
prop13a: 1,
137+
prop13b: 1
138+
})), (cnd[14] && {
139+
prop14a: 1,
140+
prop14b: 1
141+
})), (cnd[15] && {
142+
prop15a: 1,
143+
prop15b: 1
144+
})), (cnd[16] && {
145+
prop16a: 1,
146+
prop16b: 1
147+
})), (cnd[17] && {
148+
prop17a: 1,
149+
prop17b: 1
150+
})), (cnd[18] && {
151+
prop18a: 1,
152+
prop18b: 1
153+
})), (cnd[19] && {
154+
prop19a: 1,
155+
prop19b: 1
156+
})), (cnd[20] && {
157+
prop20a: 1,
158+
prop20b: 1
159+
}));
160+
}

0 commit comments

Comments
 (0)