mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #3239 from Microsoft/cyclicTypeInstantiation
Detect cycles during type instantiation
This commit is contained in:
@@ -3866,6 +3866,18 @@ module ts {
|
||||
}
|
||||
|
||||
function instantiateAnonymousType(type: ObjectType, mapper: TypeMapper): ObjectType {
|
||||
// If this type has already been instantiated using this mapper, returned the cached result. This guards against
|
||||
// infinite instantiations of cyclic types, e.g. "var x: { a: T, b: typeof x };"
|
||||
if (mapper.mappings) {
|
||||
let cached = <ObjectType>mapper.mappings[type.id];
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mapper.mappings = {};
|
||||
}
|
||||
// Instantiate the given type using the given mapper and cache the result
|
||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
|
||||
result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
|
||||
result.members = createSymbolTable(result.properties);
|
||||
@@ -3875,6 +3887,7 @@ module ts {
|
||||
let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
|
||||
if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper);
|
||||
if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper);
|
||||
mapper.mappings[type.id] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1589,6 +1589,7 @@ module ts {
|
||||
/* @internal */
|
||||
export interface TypeMapper {
|
||||
(t: TypeParameter): Type;
|
||||
mappings?: Map<Type>; // Type mapping cache
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//// [cyclicTypeInstantiation.ts]
|
||||
function foo<T>() {
|
||||
var x: {
|
||||
a: T;
|
||||
b: typeof x;
|
||||
};
|
||||
return x;
|
||||
}
|
||||
|
||||
function bar<T>() {
|
||||
var x: {
|
||||
a: T;
|
||||
b: typeof x;
|
||||
};
|
||||
return x;
|
||||
}
|
||||
|
||||
var a = foo<string>();
|
||||
var b = bar<string>();
|
||||
// Relating types of a and b produces instantiations of the cyclic anonymous types in foo and bar
|
||||
a = b;
|
||||
|
||||
|
||||
//// [cyclicTypeInstantiation.js]
|
||||
function foo() {
|
||||
var x;
|
||||
return x;
|
||||
}
|
||||
function bar() {
|
||||
var x;
|
||||
return x;
|
||||
}
|
||||
var a = foo();
|
||||
var b = bar();
|
||||
// Relating types of a and b produces instantiations of the cyclic anonymous types in foo and bar
|
||||
a = b;
|
||||
@@ -0,0 +1,54 @@
|
||||
=== tests/cases/compiler/cyclicTypeInstantiation.ts ===
|
||||
function foo<T>() {
|
||||
>foo : Symbol(foo, Decl(cyclicTypeInstantiation.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(cyclicTypeInstantiation.ts, 0, 13))
|
||||
|
||||
var x: {
|
||||
>x : Symbol(x, Decl(cyclicTypeInstantiation.ts, 1, 7))
|
||||
|
||||
a: T;
|
||||
>a : Symbol(a, Decl(cyclicTypeInstantiation.ts, 1, 12))
|
||||
>T : Symbol(T, Decl(cyclicTypeInstantiation.ts, 0, 13))
|
||||
|
||||
b: typeof x;
|
||||
>b : Symbol(b, Decl(cyclicTypeInstantiation.ts, 2, 13))
|
||||
>x : Symbol(x, Decl(cyclicTypeInstantiation.ts, 1, 7))
|
||||
|
||||
};
|
||||
return x;
|
||||
>x : Symbol(x, Decl(cyclicTypeInstantiation.ts, 1, 7))
|
||||
}
|
||||
|
||||
function bar<T>() {
|
||||
>bar : Symbol(bar, Decl(cyclicTypeInstantiation.ts, 6, 1))
|
||||
>T : Symbol(T, Decl(cyclicTypeInstantiation.ts, 8, 13))
|
||||
|
||||
var x: {
|
||||
>x : Symbol(x, Decl(cyclicTypeInstantiation.ts, 9, 7))
|
||||
|
||||
a: T;
|
||||
>a : Symbol(a, Decl(cyclicTypeInstantiation.ts, 9, 12))
|
||||
>T : Symbol(T, Decl(cyclicTypeInstantiation.ts, 8, 13))
|
||||
|
||||
b: typeof x;
|
||||
>b : Symbol(b, Decl(cyclicTypeInstantiation.ts, 10, 13))
|
||||
>x : Symbol(x, Decl(cyclicTypeInstantiation.ts, 9, 7))
|
||||
|
||||
};
|
||||
return x;
|
||||
>x : Symbol(x, Decl(cyclicTypeInstantiation.ts, 9, 7))
|
||||
}
|
||||
|
||||
var a = foo<string>();
|
||||
>a : Symbol(a, Decl(cyclicTypeInstantiation.ts, 16, 3))
|
||||
>foo : Symbol(foo, Decl(cyclicTypeInstantiation.ts, 0, 0))
|
||||
|
||||
var b = bar<string>();
|
||||
>b : Symbol(b, Decl(cyclicTypeInstantiation.ts, 17, 3))
|
||||
>bar : Symbol(bar, Decl(cyclicTypeInstantiation.ts, 6, 1))
|
||||
|
||||
// Relating types of a and b produces instantiations of the cyclic anonymous types in foo and bar
|
||||
a = b;
|
||||
>a : Symbol(a, Decl(cyclicTypeInstantiation.ts, 16, 3))
|
||||
>b : Symbol(b, Decl(cyclicTypeInstantiation.ts, 17, 3))
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
=== tests/cases/compiler/cyclicTypeInstantiation.ts ===
|
||||
function foo<T>() {
|
||||
>foo : <T>() => { a: T; b: any; }
|
||||
>T : T
|
||||
|
||||
var x: {
|
||||
>x : { a: T; b: any; }
|
||||
|
||||
a: T;
|
||||
>a : T
|
||||
>T : T
|
||||
|
||||
b: typeof x;
|
||||
>b : { a: T; b: any; }
|
||||
>x : { a: T; b: any; }
|
||||
|
||||
};
|
||||
return x;
|
||||
>x : { a: T; b: any; }
|
||||
}
|
||||
|
||||
function bar<T>() {
|
||||
>bar : <T>() => { a: T; b: any; }
|
||||
>T : T
|
||||
|
||||
var x: {
|
||||
>x : { a: T; b: any; }
|
||||
|
||||
a: T;
|
||||
>a : T
|
||||
>T : T
|
||||
|
||||
b: typeof x;
|
||||
>b : { a: T; b: any; }
|
||||
>x : { a: T; b: any; }
|
||||
|
||||
};
|
||||
return x;
|
||||
>x : { a: T; b: any; }
|
||||
}
|
||||
|
||||
var a = foo<string>();
|
||||
>a : { a: string; b: any; }
|
||||
>foo<string>() : { a: string; b: any; }
|
||||
>foo : <T>() => { a: T; b: any; }
|
||||
|
||||
var b = bar<string>();
|
||||
>b : { a: string; b: any; }
|
||||
>bar<string>() : { a: string; b: any; }
|
||||
>bar : <T>() => { a: T; b: any; }
|
||||
|
||||
// Relating types of a and b produces instantiations of the cyclic anonymous types in foo and bar
|
||||
a = b;
|
||||
>a = b : { a: string; b: any; }
|
||||
>a : { a: string; b: any; }
|
||||
>b : { a: string; b: any; }
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
function foo<T>() {
|
||||
var x: {
|
||||
a: T;
|
||||
b: typeof x;
|
||||
};
|
||||
return x;
|
||||
}
|
||||
|
||||
function bar<T>() {
|
||||
var x: {
|
||||
a: T;
|
||||
b: typeof x;
|
||||
};
|
||||
return x;
|
||||
}
|
||||
|
||||
var a = foo<string>();
|
||||
var b = bar<string>();
|
||||
// Relating types of a and b produces instantiations of the cyclic anonymous types in foo and bar
|
||||
a = b;
|
||||
Reference in New Issue
Block a user