Skip to content

Commit 607d96f

Browse files
authored
Improve performance of maybe stack in recursiveTypeRelatedTo (#55224)
1 parent 32285d9 commit 607d96f

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

src/compiler/checker.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20361,6 +20361,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2036120361
let errorInfo: DiagnosticMessageChain | undefined;
2036220362
let relatedInfo: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined;
2036320363
let maybeKeys: string[];
20364+
let maybeKeysSet: Set<string>;
2036420365
let sourceStack: Type[];
2036520366
let targetStack: Type[];
2036620367
let maybeCount = 0;
@@ -21237,27 +21238,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2123721238
}
2123821239
if (!maybeKeys) {
2123921240
maybeKeys = [];
21241+
maybeKeysSet = new Set();
2124021242
sourceStack = [];
2124121243
targetStack = [];
2124221244
}
2124321245
else {
21246+
// If source and target are already being compared, consider them related with assumptions
21247+
if (maybeKeysSet.has(id)) {
21248+
return Ternary.Maybe;
21249+
}
21250+
2124421251
// A key that starts with "*" is an indication that we have type references that reference constrained
2124521252
// type parameters. For such keys we also check against the key we would have gotten if all type parameters
2124621253
// were unconstrained.
2124721254
const broadestEquivalentId = id.startsWith("*") ? getRelationKey(source, target, intersectionState, relation, /*ignoreConstraints*/ true) : undefined;
21248-
for (let i = 0; i < maybeCount; i++) {
21249-
// If source and target are already being compared, consider them related with assumptions
21250-
if (id === maybeKeys[i] || broadestEquivalentId && broadestEquivalentId === maybeKeys[i]) {
21251-
return Ternary.Maybe;
21252-
}
21255+
if (broadestEquivalentId && maybeKeysSet.has(broadestEquivalentId)) {
21256+
return Ternary.Maybe;
2125321257
}
21258+
2125421259
if (sourceDepth === 100 || targetDepth === 100) {
2125521260
overflow = true;
2125621261
return Ternary.False;
2125721262
}
2125821263
}
2125921264
const maybeStart = maybeCount;
2126021265
maybeKeys[maybeCount] = id;
21266+
maybeKeysSet.add(id);
2126121267
maybeCount++;
2126221268
const saveExpandingFlags = expandingFlags;
2126321269
if (recursionFlags & RecursionFlags.Source) {
@@ -21313,20 +21319,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2131321319
if (result === Ternary.True || result === Ternary.Maybe) {
2131421320
// If result is definitely true, record all maybe keys as having succeeded. Also, record Ternary.Maybe
2131521321
// results as having succeeded once we reach depth 0, but never record Ternary.Unknown results.
21316-
for (let i = maybeStart; i < maybeCount; i++) {
21317-
relation.set(maybeKeys[i], RelationComparisonResult.Succeeded | propagatingVarianceFlags);
21318-
}
21322+
resetMaybeStack(/*markAllAsSucceeded*/ true);
21323+
}
21324+
else {
21325+
resetMaybeStack(/*markAllAsSucceeded*/ false);
2131921326
}
21320-
maybeCount = maybeStart;
2132121327
}
21328+
// Note: it's intentional that we don't reset in the else case;
21329+
// we leave them on the stack such that when we hit depth zero
21330+
// above, we can report all of them as successful.
2132221331
}
2132321332
else {
2132421333
// A false result goes straight into global cache (when something is false under
2132521334
// assumptions it will also be false without assumptions)
2132621335
relation.set(id, (reportErrors ? RelationComparisonResult.Reported : 0) | RelationComparisonResult.Failed | propagatingVarianceFlags);
21327-
maybeCount = maybeStart;
21336+
resetMaybeStack(/*markAllAsSucceeded*/ false);
2132821337
}
2132921338
return result;
21339+
21340+
function resetMaybeStack(markAllAsSucceeded: boolean) {
21341+
for (let i = maybeStart; i < maybeCount; i++) {
21342+
maybeKeysSet.delete(maybeKeys[i]);
21343+
if (markAllAsSucceeded) {
21344+
relation.set(maybeKeys[i], RelationComparisonResult.Succeeded | propagatingVarianceFlags);
21345+
}
21346+
}
21347+
maybeCount = maybeStart;
21348+
}
2133021349
}
2133121350

2133221351
function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {

0 commit comments

Comments
 (0)