Skip to content

Commit c7fdc0a

Browse files
committed
Merge pull request microsoft#5099 from Microsoft/deferMemberInstantiation
Defer member instantiation
2 parents 836007e + d9933c8 commit c7fdc0a

10 files changed

Lines changed: 377 additions & 19 deletions

src/compiler/checker.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3171,8 +3171,8 @@ namespace ts {
31713171
members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1);
31723172
callSignatures = instantiateList(source.declaredCallSignatures, mapper, instantiateSignature);
31733173
constructSignatures = instantiateList(source.declaredConstructSignatures, mapper, instantiateSignature);
3174-
stringIndexType = source.declaredStringIndexType ? instantiateType(source.declaredStringIndexType, mapper) : undefined;
3175-
numberIndexType = source.declaredNumberIndexType ? instantiateType(source.declaredNumberIndexType, mapper) : undefined;
3174+
stringIndexType = instantiateType(source.declaredStringIndexType, mapper);
3175+
numberIndexType = instantiateType(source.declaredNumberIndexType, mapper);
31763176
}
31773177
let baseTypes = getBaseTypes(source);
31783178
if (baseTypes.length) {
@@ -3371,15 +3371,22 @@ namespace ts {
33713371
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
33723372
}
33733373

3374-
function resolveAnonymousTypeMembers(type: ObjectType) {
3374+
function resolveAnonymousTypeMembers(type: AnonymousType) {
33753375
let symbol = type.symbol;
33763376
let members: SymbolTable;
33773377
let callSignatures: Signature[];
33783378
let constructSignatures: Signature[];
33793379
let stringIndexType: Type;
33803380
let numberIndexType: Type;
33813381

3382-
if (symbol.flags & SymbolFlags.TypeLiteral) {
3382+
if (type.target) {
3383+
members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false);
3384+
callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature);
3385+
constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature);
3386+
stringIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.String), type.mapper);
3387+
numberIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.Number), type.mapper);
3388+
}
3389+
else if (symbol.flags & SymbolFlags.TypeLiteral) {
33833390
members = symbol.members;
33843391
callSignatures = getSignaturesOfSymbol(members["__call"]);
33853392
constructSignatures = getSignaturesOfSymbol(members["__new"]);
@@ -3424,7 +3431,7 @@ namespace ts {
34243431
resolveClassOrInterfaceMembers(<InterfaceType>type);
34253432
}
34263433
else if (type.flags & TypeFlags.Anonymous) {
3427-
resolveAnonymousTypeMembers(<ObjectType>type);
3434+
resolveAnonymousTypeMembers(<AnonymousType>type);
34283435
}
34293436
else if (type.flags & TypeFlags.Tuple) {
34303437
resolveTupleTypeMembers(<TupleType>type);
@@ -4543,7 +4550,7 @@ namespace ts {
45434550
}
45444551
let result = createSignature(signature.declaration, freshTypeParameters,
45454552
instantiateList(signature.parameters, mapper, instantiateSymbol),
4546-
signature.resolvedReturnType ? instantiateType(signature.resolvedReturnType, mapper) : undefined,
4553+
instantiateType(signature.resolvedReturnType, mapper),
45474554
freshTypePredicate,
45484555
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
45494556
result.target = signature;
@@ -4575,7 +4582,7 @@ namespace ts {
45754582
return result;
45764583
}
45774584

4578-
function instantiateAnonymousType(type: ObjectType, mapper: TypeMapper): ObjectType {
4585+
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): ObjectType {
45794586
if (mapper.instantiations) {
45804587
let cachedType = mapper.instantiations[type.id];
45814588
if (cachedType) {
@@ -4586,27 +4593,21 @@ namespace ts {
45864593
mapper.instantiations = [];
45874594
}
45884595
// Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it
4589-
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol);
4590-
result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
4591-
result.members = createSymbolTable(result.properties);
4592-
result.callSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Call), mapper, instantiateSignature);
4593-
result.constructSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Construct), mapper, instantiateSignature);
4594-
let stringIndexType = getIndexTypeOfType(type, IndexKind.String);
4595-
let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
4596-
if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper);
4597-
if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper);
4596+
let result = <AnonymousType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol);
4597+
result.target = type;
4598+
result.mapper = mapper;
45984599
mapper.instantiations[type.id] = result;
45994600
return result;
46004601
}
46014602

46024603
function instantiateType(type: Type, mapper: TypeMapper): Type {
4603-
if (mapper !== identityMapper) {
4604+
if (type && mapper !== identityMapper) {
46044605
if (type.flags & TypeFlags.TypeParameter) {
46054606
return mapper(<TypeParameter>type);
46064607
}
46074608
if (type.flags & TypeFlags.Anonymous) {
46084609
return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) ?
4609-
instantiateAnonymousType(<ObjectType>type, mapper) : type;
4610+
instantiateAnonymousType(<AnonymousType>type, mapper) : type;
46104611
}
46114612
if (type.flags & TypeFlags.Reference) {
46124613
return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));

src/compiler/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1880,7 +1880,7 @@ namespace ts {
18801880
}
18811881

18821882
export interface TupleType extends ObjectType {
1883-
elementTypes: Type[]; // Element types
1883+
elementTypes: Type[]; // Element types
18841884
}
18851885

18861886
export interface UnionOrIntersectionType extends Type {
@@ -1895,6 +1895,13 @@ namespace ts {
18951895

18961896
export interface IntersectionType extends UnionOrIntersectionType { }
18971897

1898+
/* @internal */
1899+
// An instantiated anonymous type has a target and a mapper
1900+
export interface AnonymousType extends ObjectType {
1901+
target?: AnonymousType; // Instantiation target
1902+
mapper?: TypeMapper; // Instantiation mapper
1903+
}
1904+
18981905
/* @internal */
18991906
// Resolved object, union, or intersection type
19001907
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [recursiveGenericUnionType1.ts]
2+
declare module Test1 {
3+
export type Container<T> = T | {
4+
[i: string]: Container<T>;
5+
};
6+
export type IStringContainer = Container<string>;
7+
}
8+
9+
declare module Test2 {
10+
export type Container<T> = T | {
11+
[i: string]: Container<T>;
12+
};
13+
export type IStringContainer = Container<string>;
14+
}
15+
16+
var x: Test1.Container<number>;
17+
18+
var s1: Test1.IStringContainer;
19+
var s2: Test2.IStringContainer;
20+
s1 = s2;
21+
s2 = s1;
22+
23+
24+
//// [recursiveGenericUnionType1.js]
25+
var x;
26+
var s1;
27+
var s2;
28+
s1 = s2;
29+
s2 = s1;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
=== tests/cases/compiler/recursiveGenericUnionType1.ts ===
2+
declare module Test1 {
3+
>Test1 : Symbol(Test1, Decl(recursiveGenericUnionType1.ts, 0, 0))
4+
5+
export type Container<T> = T | {
6+
>Container : Symbol(Container, Decl(recursiveGenericUnionType1.ts, 0, 22))
7+
>T : Symbol(T, Decl(recursiveGenericUnionType1.ts, 1, 26))
8+
>T : Symbol(T, Decl(recursiveGenericUnionType1.ts, 1, 26))
9+
10+
[i: string]: Container<T>;
11+
>i : Symbol(i, Decl(recursiveGenericUnionType1.ts, 2, 9))
12+
>Container : Symbol(Container, Decl(recursiveGenericUnionType1.ts, 0, 22))
13+
>T : Symbol(T, Decl(recursiveGenericUnionType1.ts, 1, 26))
14+
15+
};
16+
export type IStringContainer = Container<string>;
17+
>IStringContainer : Symbol(IStringContainer, Decl(recursiveGenericUnionType1.ts, 3, 6))
18+
>Container : Symbol(Container, Decl(recursiveGenericUnionType1.ts, 0, 22))
19+
}
20+
21+
declare module Test2 {
22+
>Test2 : Symbol(Test2, Decl(recursiveGenericUnionType1.ts, 5, 1))
23+
24+
export type Container<T> = T | {
25+
>Container : Symbol(Container, Decl(recursiveGenericUnionType1.ts, 7, 22))
26+
>T : Symbol(T, Decl(recursiveGenericUnionType1.ts, 8, 26))
27+
>T : Symbol(T, Decl(recursiveGenericUnionType1.ts, 8, 26))
28+
29+
[i: string]: Container<T>;
30+
>i : Symbol(i, Decl(recursiveGenericUnionType1.ts, 9, 9))
31+
>Container : Symbol(Container, Decl(recursiveGenericUnionType1.ts, 7, 22))
32+
>T : Symbol(T, Decl(recursiveGenericUnionType1.ts, 8, 26))
33+
34+
};
35+
export type IStringContainer = Container<string>;
36+
>IStringContainer : Symbol(IStringContainer, Decl(recursiveGenericUnionType1.ts, 10, 6))
37+
>Container : Symbol(Container, Decl(recursiveGenericUnionType1.ts, 7, 22))
38+
}
39+
40+
var x: Test1.Container<number>;
41+
>x : Symbol(x, Decl(recursiveGenericUnionType1.ts, 14, 3))
42+
>Test1 : Symbol(Test1, Decl(recursiveGenericUnionType1.ts, 0, 0))
43+
>Container : Symbol(Test1.Container, Decl(recursiveGenericUnionType1.ts, 0, 22))
44+
45+
var s1: Test1.IStringContainer;
46+
>s1 : Symbol(s1, Decl(recursiveGenericUnionType1.ts, 16, 3))
47+
>Test1 : Symbol(Test1, Decl(recursiveGenericUnionType1.ts, 0, 0))
48+
>IStringContainer : Symbol(Test1.IStringContainer, Decl(recursiveGenericUnionType1.ts, 3, 6))
49+
50+
var s2: Test2.IStringContainer;
51+
>s2 : Symbol(s2, Decl(recursiveGenericUnionType1.ts, 17, 3))
52+
>Test2 : Symbol(Test2, Decl(recursiveGenericUnionType1.ts, 5, 1))
53+
>IStringContainer : Symbol(Test2.IStringContainer, Decl(recursiveGenericUnionType1.ts, 10, 6))
54+
55+
s1 = s2;
56+
>s1 : Symbol(s1, Decl(recursiveGenericUnionType1.ts, 16, 3))
57+
>s2 : Symbol(s2, Decl(recursiveGenericUnionType1.ts, 17, 3))
58+
59+
s2 = s1;
60+
>s2 : Symbol(s2, Decl(recursiveGenericUnionType1.ts, 17, 3))
61+
>s1 : Symbol(s1, Decl(recursiveGenericUnionType1.ts, 16, 3))
62+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
=== tests/cases/compiler/recursiveGenericUnionType1.ts ===
2+
declare module Test1 {
3+
>Test1 : any
4+
5+
export type Container<T> = T | {
6+
>Container : T | { [i: string]: T | any; }
7+
>T : T
8+
>T : T
9+
10+
[i: string]: Container<T>;
11+
>i : string
12+
>Container : T | { [i: string]: T | any; }
13+
>T : T
14+
15+
};
16+
export type IStringContainer = Container<string>;
17+
>IStringContainer : string | { [i: string]: string | any; }
18+
>Container : T | { [i: string]: T | any; }
19+
}
20+
21+
declare module Test2 {
22+
>Test2 : any
23+
24+
export type Container<T> = T | {
25+
>Container : T | { [i: string]: T | any; }
26+
>T : T
27+
>T : T
28+
29+
[i: string]: Container<T>;
30+
>i : string
31+
>Container : T | { [i: string]: T | any; }
32+
>T : T
33+
34+
};
35+
export type IStringContainer = Container<string>;
36+
>IStringContainer : string | { [i: string]: string | any; }
37+
>Container : T | { [i: string]: T | any; }
38+
}
39+
40+
var x: Test1.Container<number>;
41+
>x : number | { [i: string]: number | any; }
42+
>Test1 : any
43+
>Container : T | { [i: string]: T | any; }
44+
45+
var s1: Test1.IStringContainer;
46+
>s1 : string | { [i: string]: string | any; }
47+
>Test1 : any
48+
>IStringContainer : string | { [i: string]: string | any; }
49+
50+
var s2: Test2.IStringContainer;
51+
>s2 : string | { [i: string]: string | any; }
52+
>Test2 : any
53+
>IStringContainer : string | { [i: string]: string | any; }
54+
55+
s1 = s2;
56+
>s1 = s2 : string | { [i: string]: string | any; }
57+
>s1 : string | { [i: string]: string | any; }
58+
>s2 : string | { [i: string]: string | any; }
59+
60+
s2 = s1;
61+
>s2 = s1 : string | { [i: string]: string | any; }
62+
>s2 : string | { [i: string]: string | any; }
63+
>s1 : string | { [i: string]: string | any; }
64+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [recursiveGenericUnionType2.ts]
2+
declare module Test1 {
3+
export type Container<T> = T | {
4+
[i: string]: Container<T>[];
5+
};
6+
export type IStringContainer = Container<string>;
7+
}
8+
9+
declare module Test2 {
10+
export type Container<T> = T | {
11+
[i: string]: Container<T>[];
12+
};
13+
export type IStringContainer = Container<string>;
14+
}
15+
16+
var x: Test1.Container<number>;
17+
18+
var s1: Test1.IStringContainer;
19+
var s2: Test2.IStringContainer;
20+
s1 = s2;
21+
s2 = s1;
22+
23+
24+
//// [recursiveGenericUnionType2.js]
25+
var x;
26+
var s1;
27+
var s2;
28+
s1 = s2;
29+
s2 = s1;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
=== tests/cases/compiler/recursiveGenericUnionType2.ts ===
2+
declare module Test1 {
3+
>Test1 : Symbol(Test1, Decl(recursiveGenericUnionType2.ts, 0, 0))
4+
5+
export type Container<T> = T | {
6+
>Container : Symbol(Container, Decl(recursiveGenericUnionType2.ts, 0, 22))
7+
>T : Symbol(T, Decl(recursiveGenericUnionType2.ts, 1, 26))
8+
>T : Symbol(T, Decl(recursiveGenericUnionType2.ts, 1, 26))
9+
10+
[i: string]: Container<T>[];
11+
>i : Symbol(i, Decl(recursiveGenericUnionType2.ts, 2, 9))
12+
>Container : Symbol(Container, Decl(recursiveGenericUnionType2.ts, 0, 22))
13+
>T : Symbol(T, Decl(recursiveGenericUnionType2.ts, 1, 26))
14+
15+
};
16+
export type IStringContainer = Container<string>;
17+
>IStringContainer : Symbol(IStringContainer, Decl(recursiveGenericUnionType2.ts, 3, 6))
18+
>Container : Symbol(Container, Decl(recursiveGenericUnionType2.ts, 0, 22))
19+
}
20+
21+
declare module Test2 {
22+
>Test2 : Symbol(Test2, Decl(recursiveGenericUnionType2.ts, 5, 1))
23+
24+
export type Container<T> = T | {
25+
>Container : Symbol(Container, Decl(recursiveGenericUnionType2.ts, 7, 22))
26+
>T : Symbol(T, Decl(recursiveGenericUnionType2.ts, 8, 26))
27+
>T : Symbol(T, Decl(recursiveGenericUnionType2.ts, 8, 26))
28+
29+
[i: string]: Container<T>[];
30+
>i : Symbol(i, Decl(recursiveGenericUnionType2.ts, 9, 9))
31+
>Container : Symbol(Container, Decl(recursiveGenericUnionType2.ts, 7, 22))
32+
>T : Symbol(T, Decl(recursiveGenericUnionType2.ts, 8, 26))
33+
34+
};
35+
export type IStringContainer = Container<string>;
36+
>IStringContainer : Symbol(IStringContainer, Decl(recursiveGenericUnionType2.ts, 10, 6))
37+
>Container : Symbol(Container, Decl(recursiveGenericUnionType2.ts, 7, 22))
38+
}
39+
40+
var x: Test1.Container<number>;
41+
>x : Symbol(x, Decl(recursiveGenericUnionType2.ts, 14, 3))
42+
>Test1 : Symbol(Test1, Decl(recursiveGenericUnionType2.ts, 0, 0))
43+
>Container : Symbol(Test1.Container, Decl(recursiveGenericUnionType2.ts, 0, 22))
44+
45+
var s1: Test1.IStringContainer;
46+
>s1 : Symbol(s1, Decl(recursiveGenericUnionType2.ts, 16, 3))
47+
>Test1 : Symbol(Test1, Decl(recursiveGenericUnionType2.ts, 0, 0))
48+
>IStringContainer : Symbol(Test1.IStringContainer, Decl(recursiveGenericUnionType2.ts, 3, 6))
49+
50+
var s2: Test2.IStringContainer;
51+
>s2 : Symbol(s2, Decl(recursiveGenericUnionType2.ts, 17, 3))
52+
>Test2 : Symbol(Test2, Decl(recursiveGenericUnionType2.ts, 5, 1))
53+
>IStringContainer : Symbol(Test2.IStringContainer, Decl(recursiveGenericUnionType2.ts, 10, 6))
54+
55+
s1 = s2;
56+
>s1 : Symbol(s1, Decl(recursiveGenericUnionType2.ts, 16, 3))
57+
>s2 : Symbol(s2, Decl(recursiveGenericUnionType2.ts, 17, 3))
58+
59+
s2 = s1;
60+
>s2 : Symbol(s2, Decl(recursiveGenericUnionType2.ts, 17, 3))
61+
>s1 : Symbol(s1, Decl(recursiveGenericUnionType2.ts, 16, 3))
62+

0 commit comments

Comments
 (0)