@@ -93,7 +93,7 @@ module ts {
93
93
let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
94
94
let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
95
95
let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
96
-
96
+
97
97
let anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
98
98
let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
99
99
@@ -118,14 +118,18 @@ module ts {
118
118
let getGlobalParameterDecoratorType: () => ObjectType;
119
119
let getGlobalPropertyDecoratorType: () => ObjectType;
120
120
let getGlobalMethodDecoratorType: () => ObjectType;
121
-
121
+
122
122
let tupleTypes: Map<TupleType> = {};
123
123
let unionTypes: Map<UnionType> = {};
124
124
let stringLiteralTypes: Map<StringLiteralType> = {};
125
125
let emitExtends = false;
126
126
let emitDecorate = false;
127
127
let emitParam = false;
128
128
129
+ let resolutionTargets: Object[] = [];
130
+ let resolutionResults: boolean[] = [];
131
+ let resolutionCount = 0;
132
+
129
133
let mergedSymbols: Symbol[] = [];
130
134
let symbolLinks: SymbolLinks[] = [];
131
135
let nodeLinks: NodeLinks[] = [];
@@ -1980,7 +1984,7 @@ module ts {
1980
1984
}
1981
1985
}
1982
1986
1983
- function collectLinkedAliases(node: Identifier): Node[]{
1987
+ function collectLinkedAliases(node: Identifier): Node[] {
1984
1988
var exportSymbol: Symbol;
1985
1989
if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) {
1986
1990
exportSymbol = resolveName(node.parent, node.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, Diagnostics.Cannot_find_name_0, node);
@@ -2014,6 +2018,34 @@ module ts {
2014
2018
}
2015
2019
}
2016
2020
2021
+ // Push an entry on the type resolution stack. If an entry with the given target is not already on the stack,
2022
+ // a new entry with that target and an associated result value of true is pushed on the stack, and the value
2023
+ // true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and
2024
+ // all entries pushed after it are changed to false, and the value false is returned. The target object has
2025
+ // no significance other than to provide a unique identity for a particular type resolution result.
2026
+ function pushTypeResolution(target: Object): boolean {
2027
+ for (let i = 0; i < resolutionCount; i++) {
2028
+ if (resolutionTargets[i] === target) {
2029
+ do {
2030
+ resolutionResults[i++] = false;
2031
+ }
2032
+ while (i < resolutionCount);
2033
+ return false;
2034
+ }
2035
+ }
2036
+ resolutionTargets[resolutionCount] = target;
2037
+ resolutionResults[resolutionCount] = true;
2038
+ resolutionCount++;
2039
+ return true;
2040
+ }
2041
+
2042
+ // Pop an entry from the type resolution stack and return its associated result value. The result value will
2043
+ // be true if no circularities were detected, or false if a circularity was found.
2044
+ function popTypeResolution(): boolean {
2045
+ resolutionTargets[--resolutionCount] = undefined;
2046
+ return resolutionResults[resolutionCount];
2047
+ }
2048
+
2017
2049
function getRootDeclaration(node: Node): Node {
2018
2050
while (node.kind === SyntaxKind.BindingElement) {
2019
2051
node = node.parent.parent;
@@ -2271,27 +2303,27 @@ module ts {
2271
2303
return links.type = checkExpression((<ExportAssignment>declaration).expression);
2272
2304
}
2273
2305
// Handle variable, parameter or property
2274
- links.type = resolvingType;
2275
- let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
2276
- if (links.type === resolvingType) {
2277
- links.type = type;
2278
- }
2279
- }
2280
- else if (links.type === resolvingType) {
2281
- if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
2282
- // Variable has type annotation that circularly references the variable itself
2283
- links.type = unknownType;
2284
- error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
2285
- symbolToString(symbol));
2306
+ if (!pushTypeResolution(symbol)) {
2307
+ return unknownType;
2286
2308
}
2287
- else {
2288
- // Variable has initializer that circularly references the variable itself
2289
- links.type = anyType;
2290
- if (compilerOptions.noImplicitAny) {
2291
- error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
2309
+ let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
2310
+ if (!popTypeResolution()) {
2311
+ if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
2312
+ // Variable has type annotation that circularly references the variable itself
2313
+ type = unknownType;
2314
+ error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
2292
2315
symbolToString(symbol));
2293
2316
}
2317
+ else {
2318
+ // Variable has initializer that circularly references the variable itself
2319
+ type = anyType;
2320
+ if (compilerOptions.noImplicitAny) {
2321
+ error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
2322
+ symbolToString(symbol));
2323
+ }
2324
+ }
2294
2325
}
2326
+ links.type = type;
2295
2327
}
2296
2328
return links.type;
2297
2329
}
@@ -2315,19 +2347,13 @@ module ts {
2315
2347
2316
2348
function getTypeOfAccessors(symbol: Symbol): Type {
2317
2349
let links = getSymbolLinks(symbol);
2318
- checkAndStoreTypeOfAccessors(symbol, links);
2319
- return links.type;
2320
- }
2321
-
2322
- function checkAndStoreTypeOfAccessors(symbol: Symbol, links?: SymbolLinks) {
2323
- links = links || getSymbolLinks(symbol);
2324
2350
if (!links.type) {
2325
- links.type = resolvingType;
2351
+ if (!pushTypeResolution(symbol)) {
2352
+ return unknownType;
2353
+ }
2326
2354
let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
2327
2355
let setter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.SetAccessor);
2328
-
2329
2356
let type: Type;
2330
-
2331
2357
// First try to see if the user specified a return type on the get-accessor.
2332
2358
let getterReturnType = getAnnotatedAccessorType(getter);
2333
2359
if (getterReturnType) {
@@ -2349,23 +2375,20 @@ module ts {
2349
2375
if (compilerOptions.noImplicitAny) {
2350
2376
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
2351
2377
}
2352
-
2353
2378
type = anyType;
2354
2379
}
2355
2380
}
2356
2381
}
2357
-
2358
- if (links.type === resolvingType) {
2359
- links.type = type;
2360
- }
2361
- }
2362
- else if (links.type === resolvingType) {
2363
- links.type = anyType;
2364
- if (compilerOptions.noImplicitAny) {
2365
- let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
2366
- error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
2382
+ if (!popTypeResolution()) {
2383
+ type = anyType;
2384
+ if (compilerOptions.noImplicitAny) {
2385
+ let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
2386
+ error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
2387
+ }
2367
2388
}
2389
+ links.type = type;
2368
2390
}
2391
+ return links.type;
2369
2392
}
2370
2393
2371
2394
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
@@ -2458,7 +2481,7 @@ module ts {
2458
2481
return result;
2459
2482
}
2460
2483
2461
- function getBaseTypes(type: InterfaceType): ObjectType[]{
2484
+ function getBaseTypes(type: InterfaceType): ObjectType[] {
2462
2485
let typeWithBaseTypes = <InterfaceTypeWithBaseTypes>type;
2463
2486
if (!typeWithBaseTypes.baseTypes) {
2464
2487
if (type.symbol.flags & SymbolFlags.Class) {
@@ -2543,17 +2566,18 @@ module ts {
2543
2566
function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type {
2544
2567
let links = getSymbolLinks(symbol);
2545
2568
if (!links.declaredType) {
2546
- links.declaredType = resolvingType;
2569
+ // Note that we use the links object as the target here because the symbol object is used as the unique
2570
+ // identity for resolution of the 'type' property in SymbolLinks.
2571
+ if (!pushTypeResolution(links)) {
2572
+ return unknownType;
2573
+ }
2547
2574
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
2548
2575
let type = getTypeFromTypeNode(declaration.type);
2549
- if (links.declaredType === resolvingType) {
2550
- links.declaredType = type;
2576
+ if (!popTypeResolution()) {
2577
+ type = unknownType;
2578
+ error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
2551
2579
}
2552
- }
2553
- else if (links.declaredType === resolvingType) {
2554
- links.declaredType = unknownType;
2555
- let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
2556
- error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
2580
+ links.declaredType = type;
2557
2581
}
2558
2582
return links.declaredType;
2559
2583
}
@@ -3157,7 +3181,9 @@ module ts {
3157
3181
3158
3182
function getReturnTypeOfSignature(signature: Signature): Type {
3159
3183
if (!signature.resolvedReturnType) {
3160
- signature.resolvedReturnType = resolvingType;
3184
+ if (!pushTypeResolution(signature)) {
3185
+ return unknownType;
3186
+ }
3161
3187
let type: Type;
3162
3188
if (signature.target) {
3163
3189
type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper);
@@ -3168,21 +3194,19 @@ module ts {
3168
3194
else {
3169
3195
type = getReturnTypeFromBody(<FunctionLikeDeclaration>signature.declaration);
3170
3196
}
3171
- if (signature.resolvedReturnType === resolvingType) {
3172
- signature.resolvedReturnType = type;
3173
- }
3174
- }
3175
- else if (signature.resolvedReturnType === resolvingType) {
3176
- signature.resolvedReturnType = anyType;
3177
- if (compilerOptions.noImplicitAny) {
3178
- let declaration = <Declaration>signature.declaration;
3179
- if (declaration.name) {
3180
- error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name));
3181
- }
3182
- else {
3183
- error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
3197
+ if (!popTypeResolution()) {
3198
+ type = anyType;
3199
+ if (compilerOptions.noImplicitAny) {
3200
+ let declaration = <Declaration>signature.declaration;
3201
+ if (declaration.name) {
3202
+ error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name));
3203
+ }
3204
+ else {
3205
+ error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
3206
+ }
3184
3207
}
3185
3208
}
3209
+ signature.resolvedReturnType = type;
3186
3210
}
3187
3211
return signature.resolvedReturnType;
3188
3212
}
@@ -8366,8 +8390,7 @@ module ts {
8366
8390
}
8367
8391
}
8368
8392
}
8369
-
8370
- checkAndStoreTypeOfAccessors(getSymbolOfNode(node));
8393
+ getTypeOfAccessors(getSymbolOfNode(node));
8371
8394
}
8372
8395
8373
8396
checkFunctionLikeDeclaration(node);
0 commit comments