Skip to content

Commit 2b345cc

Browse files
authored
Track type recusion and symbol instantiation depth seperately in createAnonymousTypeNode (#28490)
1 parent 830be06 commit 2b345cc

9 files changed

+114
-77
lines changed

src/compiler/checker.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,7 +3201,8 @@ namespace ts {
32013201
getCurrentDirectory: host.getCurrentDirectory && (() => host.getCurrentDirectory!())
32023202
} : undefined },
32033203
encounteredError: false,
3204-
visitedSymbols: undefined,
3204+
visitedTypes: undefined,
3205+
symbolDepth: undefined,
32053206
inferTypeParameters: undefined,
32063207
approximateLength: 0
32073208
};
@@ -3432,6 +3433,7 @@ namespace ts {
34323433
}
34333434

34343435
function createAnonymousTypeNode(type: ObjectType): TypeNode {
3436+
const typeId = "" + type.id;
34353437
const symbol = type.symbol;
34363438
let id: string;
34373439
if (symbol) {
@@ -3448,7 +3450,7 @@ namespace ts {
34483450
shouldWriteTypeOfFunctionSymbol()) {
34493451
return symbolToTypeNode(symbol, context, SymbolFlags.Value);
34503452
}
3451-
else if (context.visitedSymbols && context.visitedSymbols.has(id)) {
3453+
else if (context.visitedTypes && context.visitedTypes.has(typeId)) {
34523454
// If type is an anonymous type literal in a type alias declaration, use type alias name
34533455
const typeAlias = getTypeAliasForTypeLiteral(type);
34543456
if (typeAlias) {
@@ -3457,19 +3459,35 @@ namespace ts {
34573459
}
34583460
else {
34593461
context.approximateLength += 3;
3462+
if (!(context.flags & NodeBuilderFlags.NoTruncation)) {
3463+
return createTypeReferenceNode(createIdentifier("..."), /*typeArguments*/ undefined);
3464+
}
34603465
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
34613466
}
34623467
}
34633468
else {
34643469
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
34653470
// of types allows us to catch circular references to instantiations of the same anonymous type
3466-
if (!context.visitedSymbols) {
3467-
context.visitedSymbols = createMap<true>();
3471+
if (!context.visitedTypes) {
3472+
context.visitedTypes = createMap<true>();
3473+
}
3474+
if (!context.symbolDepth) {
3475+
context.symbolDepth = createMap<number>();
34683476
}
34693477

3470-
context.visitedSymbols.set(id, true);
3478+
const depth = context.symbolDepth.get(id) || 0;
3479+
if (depth > 10) {
3480+
context.approximateLength += 3;
3481+
if (!(context.flags & NodeBuilderFlags.NoTruncation)) {
3482+
return createTypeReferenceNode(createIdentifier("..."), /*typeArguments*/ undefined);
3483+
}
3484+
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
3485+
}
3486+
context.symbolDepth.set(id, depth + 1);
3487+
context.visitedTypes.set(typeId, true);
34713488
const result = createTypeNodeFromObjectType(type);
3472-
context.visitedSymbols.delete(id);
3489+
context.visitedTypes.delete(typeId);
3490+
context.symbolDepth.set(id, depth);
34733491
return result;
34743492
}
34753493
}
@@ -3486,7 +3504,7 @@ namespace ts {
34863504
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
34873505
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
34883506
// typeof is allowed only for static/non local functions
3489-
return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedSymbols && context.visitedSymbols.has(id))) && // it is type of the symbol uses itself recursively
3507+
return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedTypes && context.visitedTypes.has(typeId))) && // it is type of the symbol uses itself recursively
34903508
(!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration!)); // TODO: GH#18217 // And the build is going to succeed without visibility error or there is no structural fallback allowed
34913509
}
34923510
}
@@ -4310,7 +4328,8 @@ namespace ts {
43104328

43114329
// State
43124330
encounteredError: boolean;
4313-
visitedSymbols: Map<true> | undefined;
4331+
visitedTypes: Map<true> | undefined;
4332+
symbolDepth: Map<number> | undefined;
43144333
inferTypeParameters: TypeParameter[] | undefined;
43154334
approximateLength: number;
43164335
truncating?: boolean;
Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,58 @@
11
=== tests/cases/compiler/cyclicGenericTypeInstantiation.ts ===
22
function foo<T>() {
3-
>foo : <T>() => { y2: any; }
3+
>foo : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
44

55
var z = foo<typeof y>();
6-
>z : { y2: any; }
7-
>foo<typeof y>() : { y2: any; }
8-
>foo : <T>() => { y2: any; }
9-
>y : { y2: any; }
6+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
7+
>foo<typeof y>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
8+
>foo : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
9+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
1010

1111
var y: {
12-
>y : { y2: any; }
12+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
1313

1414
y2: typeof z
15-
>y2 : { y2: any; }
16-
>z : { y2: any; }
15+
>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
16+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
1717

1818
};
1919
return y;
20-
>y : { y2: any; }
20+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
2121
}
2222

2323

2424
function bar<T>() {
25-
>bar : <T>() => { y2: any; }
25+
>bar : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
2626

2727
var z = bar<typeof y>();
28-
>z : { y2: any; }
29-
>bar<typeof y>() : { y2: any; }
30-
>bar : <T>() => { y2: any; }
31-
>y : { y2: any; }
28+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
29+
>bar<typeof y>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
30+
>bar : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
31+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
3232

3333
var y: {
34-
>y : { y2: any; }
34+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
3535

3636
y2: typeof z;
37-
>y2 : { y2: any; }
38-
>z : { y2: any; }
37+
>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
38+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
3939
}
4040
return y;
41-
>y : { y2: any; }
41+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
4242
}
4343

4444
var a = foo<number>();
45-
>a : { y2: any; }
46-
>foo<number>() : { y2: any; }
47-
>foo : <T>() => { y2: any; }
45+
>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
46+
>foo<number>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
47+
>foo : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
4848

4949
var b = bar<number>();
50-
>b : { y2: any; }
51-
>bar<number>() : { y2: any; }
52-
>bar : <T>() => { y2: any; }
50+
>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
51+
>bar<number>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
52+
>bar : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
5353

5454
a = b;
55-
>a = b : { y2: any; }
56-
>a : { y2: any; }
57-
>b : { y2: any; }
55+
>a = b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
56+
>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
57+
>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
5858

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,63 @@
11
=== tests/cases/compiler/cyclicGenericTypeInstantiationInference.ts ===
22
function foo<T>() {
3-
>foo : <T>() => { y2: any; }
3+
>foo : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
44

55
var z = foo<typeof y>();
6-
>z : { y2: any; }
7-
>foo<typeof y>() : { y2: any; }
8-
>foo : <T>() => { y2: any; }
9-
>y : { y2: any; }
6+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
7+
>foo<typeof y>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
8+
>foo : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
9+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
1010

1111
var y: {
12-
>y : { y2: any; }
12+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
1313

1414
y2: typeof z
15-
>y2 : { y2: any; }
16-
>z : { y2: any; }
15+
>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
16+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
1717

1818
};
1919
return y;
20-
>y : { y2: any; }
20+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
2121
}
2222

2323

2424
function bar<T>() {
25-
>bar : <T>() => { y2: any; }
25+
>bar : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
2626

2727
var z = bar<typeof y>();
28-
>z : { y2: any; }
29-
>bar<typeof y>() : { y2: any; }
30-
>bar : <T>() => { y2: any; }
31-
>y : { y2: any; }
28+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
29+
>bar<typeof y>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
30+
>bar : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
31+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
3232

3333
var y: {
34-
>y : { y2: any; }
34+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
3535

3636
y2: typeof z;
37-
>y2 : { y2: any; }
38-
>z : { y2: any; }
37+
>y2 : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
38+
>z : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
3939
}
4040
return y;
41-
>y : { y2: any; }
41+
>y : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
4242
}
4343

4444
var a = foo<number>();
45-
>a : { y2: any; }
46-
>foo<number>() : { y2: any; }
47-
>foo : <T>() => { y2: any; }
45+
>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
46+
>foo<number>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
47+
>foo : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
4848

4949
var b = bar<number>();
50-
>b : { y2: any; }
51-
>bar<number>() : { y2: any; }
52-
>bar : <T>() => { y2: any; }
50+
>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
51+
>bar<number>() : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
52+
>bar : <T>() => { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
5353

5454
function test<T>(x: typeof a): void { }
55-
>test : <T>(x: { y2: any; }) => void
56-
>x : { y2: any; }
57-
>a : { y2: any; }
55+
>test : <T>(x: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }) => void
56+
>x : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
57+
>a : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
5858

5959
test(b);
6060
>test(b) : void
61-
>test : <T>(x: { y2: any; }) => void
62-
>b : { y2: any; }
61+
>test : <T>(x: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }) => void
62+
>b : { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: { y2: any; }; }; }; }; }; }; }; }; }; }; }
6363

tests/baselines/reference/genericCallWithObjectLiteralArgs.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ var r2 = foo({ bar: 1, baz: 1 }); // T = number
3030
>1 : 1
3131

3232
var r3 = foo({ bar: foo, baz: foo }); // T = typeof foo
33-
>r3 : { bar: <T>(x: any) => any; baz: <T>(x: any) => any; }
34-
>foo({ bar: foo, baz: foo }) : { bar: <T>(x: any) => any; baz: <T>(x: any) => any; }
33+
>r3 : { bar: <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }; baz: <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }; }
34+
>foo({ bar: foo, baz: foo }) : { bar: <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }; baz: <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }; }
3535
>foo : <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }
3636
>{ bar: foo, baz: foo } : { bar: <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }; baz: <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }; }
3737
>bar : <T>(x: { bar: T; baz: T; }) => { bar: T; baz: T; }

tests/baselines/reference/limitDeepInstantiations.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Repro from #14837
33

44
type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
5-
>Foo : { "true": any[T]; }[T]
6-
>"true" : { "true": any[T]; }[T]
5+
>Foo : { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": any[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]
6+
>"true" : { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": { "true": any[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]; }[T]
77

88
let f1: Foo<"true", {}>;
99
>f1 : any

tests/baselines/reference/moduleExportPropertyAssignmentDefault.types

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ var axios = {}
44
>{} : {}
55

66
module.exports = axios // both assignments should be ok
7-
>module.exports = axios : { default: any; }
8-
>module.exports : { default: any; }
9-
>module : { "tests/cases/conformance/salsa/axios": { default: any; }; }
10-
>exports : { default: any; }
7+
>module.exports = axios : { default: { default: any; }; }
8+
>module.exports : { default: { default: any; }; }
9+
>module : { "tests/cases/conformance/salsa/axios": { default: { default: any; }; }; }
10+
>exports : { default: { default: any; }; }
1111
>axios : { default: { default: any; }; }
1212

1313
module.exports.default = axios
1414
>module.exports.default = axios : { default: { default: any; }; }
1515
>module.exports.default : { default: any; }
16-
>module.exports : { default: any; }
17-
>module : { "tests/cases/conformance/salsa/axios": { default: any; }; }
18-
>exports : { default: any; }
16+
>module.exports : { default: { default: any; }; }
17+
>module : { "tests/cases/conformance/salsa/axios": { default: { default: any; }; }; }
18+
>exports : { default: { default: any; }; }
1919
>default : { default: any; }
2020
>axios : { default: { default: any; }; }
2121

tests/baselines/reference/recursiveLetConst.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ let z1 = function () { return z1; }
6363

6464
let z2 = { f() { return z2;}}
6565
>z2 : { f(): any; }
66-
>{ f() { return z2;}} : { f(): any; }
66+
>{ f() { return z2;}} : { f(): { f(): any; }; }
6767
>f : () => { f(): any; }
6868
>z2 : { f(): any; }
6969

tests/cases/fourslash/findAllRefsForFunctionExpression01.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
/////// <reference path="file1.ts" />
1010
////foo();
1111

12-
verify.singleReferenceGroup("(local function) foo(a?: void, b?: () => (a?: void, b?: any) => void): void");
12+
verify.singleReferenceGroup("(local function) foo(a?: void, b?: () => (a?: void, b?: ...) => void): void");
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////declare function schema<T> (value : T) : {field : T};
4+
////
5+
////declare const b: boolean;
6+
////const obj/*1*/ = schema(b);
7+
////const actualTypeOfNested/*2*/ = schema(obj);
8+
9+
verify.quickInfos({
10+
1: `const obj: {
11+
field: boolean;
12+
}`,
13+
2: `const actualTypeOfNested: {
14+
field: {
15+
field: boolean;
16+
};
17+
}`
18+
});

0 commit comments

Comments
 (0)