Skip to content

Commit 9ff378a

Browse files
authored
Exclude types originating in literals from recursion depth limiter check (microsoft#34742)
* Exclude types originating in literals from recursion depth limiter check * Add tests * Accept new baselines * Remove superfluous test
1 parent 2346808 commit 9ff378a

File tree

6 files changed

+385
-1
lines changed

6 files changed

+385
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16346,7 +16346,7 @@ namespace ts {
1634616346
// for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][P3][P4][P5]`).
1634716347
function isDeeplyNestedType(type: Type, stack: Type[], depth: number): boolean {
1634816348
// We track all object types that have an associated symbol (representing the origin of the type)
16349-
if (depth >= 5 && type.flags & TypeFlags.Object) {
16349+
if (depth >= 5 && type.flags & TypeFlags.Object && !isObjectOrArrayLiteralType(type)) {
1635016350
const symbol = type.symbol;
1635116351
if (symbol) {
1635216352
let count = 0;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
tests/cases/compiler/deeplyNestedCheck.ts(34,25): error TS2741: Property 'i' is missing in type '{}' but required in type 'H'.
2+
tests/cases/compiler/deeplyNestedCheck.ts(52,35): error TS2322: Type 'number' is not assignable to type 'string'.
3+
tests/cases/compiler/deeplyNestedCheck.ts(53,50): error TS2322: Type 'number' is not assignable to type 'string'.
4+
5+
6+
==== tests/cases/compiler/deeplyNestedCheck.ts (3 errors) ====
7+
// Repro from #14794
8+
9+
interface DataSnapshot<X = {}> {
10+
child(path: string): DataSnapshot;
11+
}
12+
13+
interface Snapshot<T> extends DataSnapshot {
14+
child<U extends Extract<keyof T, string>>(path: U): Snapshot<T[U]>;
15+
}
16+
17+
// Repro from 34619
18+
19+
interface A { b: B[] }
20+
interface B { c: C }
21+
interface C { d: D[] }
22+
interface D { e: E[] }
23+
interface E { f: F[] }
24+
interface F { g: G }
25+
interface G { h: H[] }
26+
interface H { i: string }
27+
28+
const x: A = {
29+
b: [
30+
{
31+
c: {
32+
d: [
33+
{
34+
e: [
35+
{
36+
f: [
37+
{
38+
g: {
39+
h: [
40+
{
41+
~
42+
// i: '',
43+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44+
},
45+
~~~~~~~~~~~~~~~~~~~~~~~~~
46+
!!! error TS2741: Property 'i' is missing in type '{}' but required in type 'H'.
47+
!!! related TS2728 tests/cases/compiler/deeplyNestedCheck.ts:20:15: 'i' is declared here.
48+
],
49+
},
50+
},
51+
],
52+
},
53+
],
54+
},
55+
],
56+
},
57+
},
58+
],
59+
};
60+
61+
// Repro from 34619
62+
63+
const a1: string[][][][][] = [[[[[42]]]]];
64+
~~
65+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
66+
const a2: string[][][][][][][][][][] = [[[[[[[[[[42]]]]]]]]]];
67+
~~
68+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
69+

tests/baselines/reference/deeplyNestedCheck.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,81 @@ interface DataSnapshot<X = {}> {
88
interface Snapshot<T> extends DataSnapshot {
99
child<U extends Extract<keyof T, string>>(path: U): Snapshot<T[U]>;
1010
}
11+
12+
// Repro from 34619
13+
14+
interface A { b: B[] }
15+
interface B { c: C }
16+
interface C { d: D[] }
17+
interface D { e: E[] }
18+
interface E { f: F[] }
19+
interface F { g: G }
20+
interface G { h: H[] }
21+
interface H { i: string }
22+
23+
const x: A = {
24+
b: [
25+
{
26+
c: {
27+
d: [
28+
{
29+
e: [
30+
{
31+
f: [
32+
{
33+
g: {
34+
h: [
35+
{
36+
// i: '',
37+
},
38+
],
39+
},
40+
},
41+
],
42+
},
43+
],
44+
},
45+
],
46+
},
47+
},
48+
],
49+
};
50+
51+
// Repro from 34619
52+
53+
const a1: string[][][][][] = [[[[[42]]]]];
54+
const a2: string[][][][][][][][][][] = [[[[[[[[[[42]]]]]]]]]];
1155

1256

1357
//// [deeplyNestedCheck.js]
1458
// Repro from #14794
59+
var x = {
60+
b: [
61+
{
62+
c: {
63+
d: [
64+
{
65+
e: [
66+
{
67+
f: [
68+
{
69+
g: {
70+
h: [
71+
{
72+
// i: '',
73+
},
74+
]
75+
}
76+
},
77+
]
78+
},
79+
]
80+
},
81+
]
82+
}
83+
},
84+
]
85+
};
86+
// Repro from 34619
87+
var a1 = [[[[[42]]]]];
88+
var a2 = [[[[[[[[[[42]]]]]]]]]];

tests/baselines/reference/deeplyNestedCheck.symbols

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,92 @@ interface Snapshot<T> extends DataSnapshot {
2828
>U : Symbol(U, Decl(deeplyNestedCheck.ts, 7, 8))
2929
}
3030

31+
// Repro from 34619
32+
33+
interface A { b: B[] }
34+
>A : Symbol(A, Decl(deeplyNestedCheck.ts, 8, 1))
35+
>b : Symbol(A.b, Decl(deeplyNestedCheck.ts, 12, 13))
36+
>B : Symbol(B, Decl(deeplyNestedCheck.ts, 12, 22))
37+
38+
interface B { c: C }
39+
>B : Symbol(B, Decl(deeplyNestedCheck.ts, 12, 22))
40+
>c : Symbol(B.c, Decl(deeplyNestedCheck.ts, 13, 13))
41+
>C : Symbol(C, Decl(deeplyNestedCheck.ts, 13, 20))
42+
43+
interface C { d: D[] }
44+
>C : Symbol(C, Decl(deeplyNestedCheck.ts, 13, 20))
45+
>d : Symbol(C.d, Decl(deeplyNestedCheck.ts, 14, 13))
46+
>D : Symbol(D, Decl(deeplyNestedCheck.ts, 14, 22))
47+
48+
interface D { e: E[] }
49+
>D : Symbol(D, Decl(deeplyNestedCheck.ts, 14, 22))
50+
>e : Symbol(D.e, Decl(deeplyNestedCheck.ts, 15, 13))
51+
>E : Symbol(E, Decl(deeplyNestedCheck.ts, 15, 22))
52+
53+
interface E { f: F[] }
54+
>E : Symbol(E, Decl(deeplyNestedCheck.ts, 15, 22))
55+
>f : Symbol(E.f, Decl(deeplyNestedCheck.ts, 16, 13))
56+
>F : Symbol(F, Decl(deeplyNestedCheck.ts, 16, 22))
57+
58+
interface F { g: G }
59+
>F : Symbol(F, Decl(deeplyNestedCheck.ts, 16, 22))
60+
>g : Symbol(F.g, Decl(deeplyNestedCheck.ts, 17, 13))
61+
>G : Symbol(G, Decl(deeplyNestedCheck.ts, 17, 20))
62+
63+
interface G { h: H[] }
64+
>G : Symbol(G, Decl(deeplyNestedCheck.ts, 17, 20))
65+
>h : Symbol(G.h, Decl(deeplyNestedCheck.ts, 18, 13))
66+
>H : Symbol(H, Decl(deeplyNestedCheck.ts, 18, 22))
67+
68+
interface H { i: string }
69+
>H : Symbol(H, Decl(deeplyNestedCheck.ts, 18, 22))
70+
>i : Symbol(H.i, Decl(deeplyNestedCheck.ts, 19, 13))
71+
72+
const x: A = {
73+
>x : Symbol(x, Decl(deeplyNestedCheck.ts, 21, 5))
74+
>A : Symbol(A, Decl(deeplyNestedCheck.ts, 8, 1))
75+
76+
b: [
77+
>b : Symbol(b, Decl(deeplyNestedCheck.ts, 21, 14))
78+
{
79+
c: {
80+
>c : Symbol(c, Decl(deeplyNestedCheck.ts, 23, 5))
81+
82+
d: [
83+
>d : Symbol(d, Decl(deeplyNestedCheck.ts, 24, 10))
84+
{
85+
e: [
86+
>e : Symbol(e, Decl(deeplyNestedCheck.ts, 26, 11))
87+
{
88+
f: [
89+
>f : Symbol(f, Decl(deeplyNestedCheck.ts, 28, 15))
90+
{
91+
g: {
92+
>g : Symbol(g, Decl(deeplyNestedCheck.ts, 30, 19))
93+
94+
h: [
95+
>h : Symbol(h, Decl(deeplyNestedCheck.ts, 31, 24))
96+
{
97+
// i: '',
98+
},
99+
],
100+
},
101+
},
102+
],
103+
},
104+
],
105+
},
106+
],
107+
},
108+
},
109+
],
110+
};
111+
112+
// Repro from 34619
113+
114+
const a1: string[][][][][] = [[[[[42]]]]];
115+
>a1 : Symbol(a1, Decl(deeplyNestedCheck.ts, 51, 5))
116+
117+
const a2: string[][][][][][][][][][] = [[[[[[[[[[42]]]]]]]]]];
118+
>a2 : Symbol(a2, Decl(deeplyNestedCheck.ts, 52, 5))
119+

tests/baselines/reference/deeplyNestedCheck.types

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,111 @@ interface Snapshot<T> extends DataSnapshot {
1313
>path : U
1414
}
1515

16+
// Repro from 34619
17+
18+
interface A { b: B[] }
19+
>b : B[]
20+
21+
interface B { c: C }
22+
>c : C
23+
24+
interface C { d: D[] }
25+
>d : D[]
26+
27+
interface D { e: E[] }
28+
>e : E[]
29+
30+
interface E { f: F[] }
31+
>f : F[]
32+
33+
interface F { g: G }
34+
>g : G
35+
36+
interface G { h: H[] }
37+
>h : H[]
38+
39+
interface H { i: string }
40+
>i : string
41+
42+
const x: A = {
43+
>x : A
44+
>{ b: [ { c: { d: [ { e: [ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ], }, ], }, }, ],} : { b: { c: { d: { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]; }; }[]; }
45+
46+
b: [
47+
>b : { c: { d: { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]; }; }[]
48+
>[ { c: { d: [ { e: [ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ], }, ], }, }, ] : { c: { d: { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]; }; }[]
49+
{
50+
>{ c: { d: [ { e: [ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ], }, ], }, } : { c: { d: { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]; }; }
51+
52+
c: {
53+
>c : { d: { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]; }
54+
>{ d: [ { e: [ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ], }, ], } : { d: { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]; }
55+
56+
d: [
57+
>d : { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]
58+
>[ { e: [ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ], }, ] : { e: { f: { g: { h: {}[]; }; }[]; }[]; }[]
59+
{
60+
>{ e: [ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ], } : { e: { f: { g: { h: {}[]; }; }[]; }[]; }
61+
62+
e: [
63+
>e : { f: { g: { h: {}[]; }; }[]; }[]
64+
>[ { f: [ { g: { h: [ { // i: '', }, ], }, }, ], }, ] : { f: { g: { h: {}[]; }; }[]; }[]
65+
{
66+
>{ f: [ { g: { h: [ { // i: '', }, ], }, }, ], } : { f: { g: { h: {}[]; }; }[]; }
67+
68+
f: [
69+
>f : { g: { h: {}[]; }; }[]
70+
>[ { g: { h: [ { // i: '', }, ], }, }, ] : { g: { h: {}[]; }; }[]
71+
{
72+
>{ g: { h: [ { // i: '', }, ], }, } : { g: { h: {}[]; }; }
73+
74+
g: {
75+
>g : { h: {}[]; }
76+
>{ h: [ { // i: '', }, ], } : { h: {}[]; }
77+
78+
h: [
79+
>h : {}[]
80+
>[ { // i: '', }, ] : {}[]
81+
{
82+
>{ // i: '', } : {}
83+
84+
// i: '',
85+
},
86+
],
87+
},
88+
},
89+
],
90+
},
91+
],
92+
},
93+
],
94+
},
95+
},
96+
],
97+
};
98+
99+
// Repro from 34619
100+
101+
const a1: string[][][][][] = [[[[[42]]]]];
102+
>a1 : string[][][][][]
103+
>[[[[[42]]]]] : number[][][][][]
104+
>[[[[42]]]] : number[][][][]
105+
>[[[42]]] : number[][][]
106+
>[[42]] : number[][]
107+
>[42] : number[]
108+
>42 : 42
109+
110+
const a2: string[][][][][][][][][][] = [[[[[[[[[[42]]]]]]]]]];
111+
>a2 : string[][][][][][][][][][]
112+
>[[[[[[[[[[42]]]]]]]]]] : number[][][][][][][][][][]
113+
>[[[[[[[[[42]]]]]]]]] : number[][][][][][][][][]
114+
>[[[[[[[[42]]]]]]]] : number[][][][][][][][]
115+
>[[[[[[[42]]]]]]] : number[][][][][][][]
116+
>[[[[[[42]]]]]] : number[][][][][][]
117+
>[[[[[42]]]]] : number[][][][][]
118+
>[[[[42]]]] : number[][][][]
119+
>[[[42]]] : number[][][]
120+
>[[42]] : number[][]
121+
>[42] : number[]
122+
>42 : 42
123+

0 commit comments

Comments
 (0)