Skip to content

Commit

Permalink
Merge pull request #15011 from Microsoft/limitDeepInstantiations
Browse files Browse the repository at this point in the history
Limit deep generic type instantiations
  • Loading branch information
ahejlsberg authored Apr 5, 2017
2 parents 90648fd + 6e58f61 commit 9d2b57a
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 7 deletions.
24 changes: 17 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace ts {

let typeCount = 0;
let symbolCount = 0;
let symbolInstantiationDepth = 0;

const emptyArray: any[] = [];
const emptySymbols = createMap<Symbol>();
Expand Down Expand Up @@ -4449,14 +4450,22 @@ namespace ts {
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
const links = getSymbolLinks(symbol);
if (!links.type) {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return unknownType;
if (symbolInstantiationDepth === 100) {
error(symbol.valueDeclaration, Diagnostics.Generic_type_instantiation_is_excessively_deep_and_possibly_infinite);
links.type = unknownType;
}
let type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
if (!popTypeResolution()) {
type = reportCircularityError(symbol);
else {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return unknownType;
}
symbolInstantiationDepth++;
let type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
symbolInstantiationDepth--;
if (!popTypeResolution()) {
type = reportCircularityError(symbol);
}
links.type = type;
}
links.type = type;
}
return links.type;
}
Expand Down Expand Up @@ -7266,8 +7275,9 @@ namespace ts {
else {
error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
}
return unknownType;
}
return unknownType;
return anyType;
}

function getIndexedAccessForMappedType(type: MappedType, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1827,6 +1827,10 @@
"category": "Error",
"code": 2549
},
"Generic type instantiation is excessively deep and possibly infinite.": {
"category": "Error",
"code": 2550
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
Expand Down
15 changes: 15 additions & 0 deletions tests/baselines/reference/limitDeepInstantiations.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2550: Generic type instantiation is excessively deep and possibly infinite.
tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'.


==== tests/cases/compiler/limitDeepInstantiations.ts (2 errors) ====
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2550: Generic type instantiation is excessively deep and possibly infinite.
let f1: Foo<"true", {}>;
let f2: Foo<"false", {}>;
~~~~~~~
!!! error TS2344: Type '"false"' does not satisfy the constraint '"true"'.

12 changes: 12 additions & 0 deletions tests/baselines/reference/limitDeepInstantiations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//// [limitDeepInstantiations.ts]
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
let f1: Foo<"true", {}>;
let f2: Foo<"false", {}>;


//// [limitDeepInstantiations.js]
// Repro from #14837
var f1;
var f2;
5 changes: 5 additions & 0 deletions tests/cases/compiler/limitDeepInstantiations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
let f1: Foo<"true", {}>;
let f2: Foo<"false", {}>;

0 comments on commit 9d2b57a

Please sign in to comment.