@@ -118,6 +118,7 @@ import {
118118 createPrinterWithRemoveCommentsNeverAsciiEscape,
119119 createPrinterWithRemoveCommentsOmitTrailingSemicolon,
120120 createPropertyNameNodeForIdentifierOrLiteral,
121+ createStackSet,
121122 createSymbolTable,
122123 createTextWriter,
123124 Debug,
@@ -962,6 +963,7 @@ import {
962963 SourceFile,
963964 SpreadAssignment,
964965 SpreadElement,
966+ StackSet,
965967 startsWith,
966968 Statement,
967969 stringContains,
@@ -20348,10 +20350,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2034820350
2034920351 let errorInfo: DiagnosticMessageChain | undefined;
2035020352 let relatedInfo: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined;
20351- let maybeKeys: string[] ;
20353+ let maybeKeys: StackSet< string> ;
2035220354 let sourceStack: Type[];
2035320355 let targetStack: Type[];
20354- let maybeCount = 0;
2035520356 let sourceDepth = 0;
2035620357 let targetDepth = 0;
2035720358 let expandingFlags = ExpandingFlags.None;
@@ -21224,29 +21225,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2122421225 }
2122521226 }
2122621227 if (!maybeKeys) {
21227- maybeKeys = [] ;
21228+ maybeKeys = createStackSet() ;
2122821229 sourceStack = [];
2122921230 targetStack = [];
2123021231 }
2123121232 else {
21233+ // If source and target are already being compared, consider them related with assumptions
21234+ if (maybeKeys.has(id)) {
21235+ return Ternary.Maybe;
21236+ }
21237+
2123221238 // A key that starts with "*" is an indication that we have type references that reference constrained
2123321239 // type parameters. For such keys we also check against the key we would have gotten if all type parameters
2123421240 // were unconstrained.
2123521241 const broadestEquivalentId = id.startsWith("*") ? getRelationKey(source, target, intersectionState, relation, /*ignoreConstraints*/ true) : undefined;
21236- for (let i = 0; i < maybeCount; i++) {
21237- // If source and target are already being compared, consider them related with assumptions
21238- if (id === maybeKeys[i] || broadestEquivalentId && broadestEquivalentId === maybeKeys[i]) {
21239- return Ternary.Maybe;
21240- }
21242+ if (broadestEquivalentId && maybeKeys.has(broadestEquivalentId)) {
21243+ return Ternary.Maybe;
2124121244 }
21245+
2124221246 if (sourceDepth === 100 || targetDepth === 100) {
2124321247 overflow = true;
2124421248 return Ternary.False;
2124521249 }
2124621250 }
21247- const maybeStart = maybeCount;
21248- maybeKeys[maybeCount] = id;
21249- maybeCount++;
21251+ const maybeStart = maybeKeys.size;
21252+ maybeKeys.push(id);
2125021253 const saveExpandingFlags = expandingFlags;
2125121254 if (recursionFlags & RecursionFlags.Source) {
2125221255 sourceStack[sourceDepth] = source;
@@ -21301,18 +21304,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2130121304 if (result === Ternary.True || result === Ternary.Maybe) {
2130221305 // If result is definitely true, record all maybe keys as having succeeded. Also, record Ternary.Maybe
2130321306 // results as having succeeded once we reach depth 0, but never record Ternary.Unknown results.
21304- for (let i = maybeStart; i < maybeCount; i++) {
21305- relation.set(maybeKeys[i], RelationComparisonResult.Succeeded | propagatingVarianceFlags);
21307+ while (maybeKeys.size > maybeStart) {
21308+ const id = maybeKeys.pop();
21309+ relation.set(id, RelationComparisonResult.Succeeded | propagatingVarianceFlags);
21310+ }
21311+ }
21312+ else {
21313+ while (maybeKeys.size > maybeStart) {
21314+ maybeKeys.pop();
2130621315 }
2130721316 }
21308- maybeCount = maybeStart;
2130921317 }
21318+ // Note: it's intentional that we don't pop in the else case;
21319+ // we leave them on the stack such that when we hit depth zero
21320+ // above, we can report all of them as successful.
2131021321 }
2131121322 else {
2131221323 // A false result goes straight into global cache (when something is false under
2131321324 // assumptions it will also be false without assumptions)
2131421325 relation.set(id, (reportErrors ? RelationComparisonResult.Reported : 0) | RelationComparisonResult.Failed | propagatingVarianceFlags);
21315- maybeCount = maybeStart;
21326+ while (maybeKeys.size > maybeStart) {
21327+ maybeKeys.pop();
21328+ }
2131621329 }
2131721330 return result;
2131821331 }
0 commit comments