Skip to content

Commit 48588b6

Browse files
committed
Only consider a type resolution sequence a cycle if none of the items in the sequence have types
1 parent fbe4246 commit 48588b6

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

src/compiler/checker.ts

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ namespace ts {
161161

162162
let resolutionTargets: Object[] = [];
163163
let resolutionResults: boolean[] = [];
164+
let resolutionKinds: TypeSystemObjectKind[] = [];
164165

165166
let mergedSymbols: Symbol[] = [];
166167
let symbolLinks: SymbolLinks[] = [];
@@ -201,6 +202,13 @@ namespace ts {
201202
let assignableRelation: Map<RelationComparisonResult> = {};
202203
let identityRelation: Map<RelationComparisonResult> = {};
203204

205+
enum TypeSystemObjectKind {
206+
Symbol,
207+
Type,
208+
SymbolLinks,
209+
Signature
210+
}
211+
204212
initializeTypeChecker();
205213

206214
return checker;
@@ -2184,13 +2192,14 @@ namespace ts {
21842192
// a unique identity for a particular type resolution result: Symbol instances are used to track resolution of
21852193
// SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and
21862194
// Signature instances are used to track resolution of Signature.resolvedReturnType.
2187-
function pushTypeResolution(target: Object): boolean {
2188-
let i = 0;
2195+
function pushTypeResolution(target: Object, flags: TypeSystemObjectKind): boolean {
21892196
let count = resolutionTargets.length;
2190-
while (i < count && resolutionTargets[i] !== target) {
2191-
i++;
2197+
let i = count - 1;
2198+
let foundGoodType = false;
2199+
while (i >= 0 && !(foundGoodType = !!hasType(resolutionTargets[i], resolutionKinds[i])) && resolutionTargets[i] !== target) {
2200+
i--;
21922201
}
2193-
if (i < count) {
2202+
if (i >= 0 && !foundGoodType) {
21942203
do {
21952204
resolutionResults[i++] = false;
21962205
}
@@ -2199,13 +2208,33 @@ namespace ts {
21992208
}
22002209
resolutionTargets.push(target);
22012210
resolutionResults.push(true);
2211+
resolutionKinds.push(flags);
22022212
return true;
22032213
}
22042214

2215+
function hasType(target: Object, flags: TypeSystemObjectKind): Type {
2216+
if (flags === TypeSystemObjectKind.Symbol) {
2217+
return getSymbolLinks(<Symbol>target).type;
2218+
}
2219+
else if (flags === TypeSystemObjectKind.Type) {
2220+
Debug.assert(!!((<Type>target).flags & TypeFlags.Class));
2221+
return (<InterfaceType>target).resolvedBaseConstructorType;
2222+
}
2223+
else if (flags === TypeSystemObjectKind.SymbolLinks) {
2224+
return (<SymbolLinks>target).declaredType;
2225+
}
2226+
else if (flags === TypeSystemObjectKind.Signature) {
2227+
return (<Signature>target).resolvedReturnType;
2228+
}
2229+
2230+
Debug.fail("Unhandled TypeSystemObjectKind");
2231+
}
2232+
22052233
// Pop an entry from the type resolution stack and return its associated result value. The result value will
22062234
// be true if no circularities were detected, or false if a circularity was found.
22072235
function popTypeResolution(): boolean {
22082236
resolutionTargets.pop();
2237+
resolutionKinds.pop();
22092238
return resolutionResults.pop();
22102239
}
22112240

@@ -2468,7 +2497,7 @@ namespace ts {
24682497
return links.type = checkExpression((<ExportAssignment>declaration).expression);
24692498
}
24702499
// Handle variable, parameter or property
2471-
if (!pushTypeResolution(symbol)) {
2500+
if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) {
24722501
return unknownType;
24732502
}
24742503
let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
@@ -2509,7 +2538,7 @@ namespace ts {
25092538
function getTypeOfAccessors(symbol: Symbol): Type {
25102539
let links = getSymbolLinks(symbol);
25112540
if (!links.type) {
2512-
if (!pushTypeResolution(symbol)) {
2541+
if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) {
25132542
return unknownType;
25142543
}
25152544
let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
@@ -2725,7 +2754,7 @@ namespace ts {
27252754
if (!baseTypeNode) {
27262755
return type.resolvedBaseConstructorType = undefinedType;
27272756
}
2728-
if (!pushTypeResolution(type)) {
2757+
if (!pushTypeResolution(type, TypeSystemObjectKind.Type)) {
27292758
return unknownType;
27302759
}
27312760
let baseConstructorType = checkExpression(baseTypeNode.expression);
@@ -2852,7 +2881,7 @@ namespace ts {
28522881
if (!links.declaredType) {
28532882
// Note that we use the links object as the target here because the symbol object is used as the unique
28542883
// identity for resolution of the 'type' property in SymbolLinks.
2855-
if (!pushTypeResolution(links)) {
2884+
if (!pushTypeResolution(links, TypeSystemObjectKind.SymbolLinks)) {
28562885
return unknownType;
28572886
}
28582887
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
@@ -3539,7 +3568,7 @@ namespace ts {
35393568

35403569
function getReturnTypeOfSignature(signature: Signature): Type {
35413570
if (!signature.resolvedReturnType) {
3542-
if (!pushTypeResolution(signature)) {
3571+
if (!pushTypeResolution(signature, TypeSystemObjectKind.Signature)) {
35433572
return unknownType;
35443573
}
35453574
let type: Type;

0 commit comments

Comments
 (0)