More efficient recording of intermediate results in type relations

This commit is contained in:
Anders Hejlsberg 2017-06-20 11:38:09 -10:00
parent a2776648cd
commit 21732eb56f

View file

@ -8733,11 +8733,12 @@ namespace ts {
containingMessageChain?: DiagnosticMessageChain): boolean {
let errorInfo: DiagnosticMessageChain;
let maybeKeys: string[];
let sourceStack: Type[];
let targetStack: Type[];
let maybeStack: Map<RelationComparisonResult>[];
let expandingFlags: number;
let maybeCount = 0;
let depth = 0;
let expandingFlags = 0;
let overflow = false;
let isIntersectionConstituent = false;
@ -9105,10 +9106,15 @@ namespace ts {
return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
}
}
if (depth > 0) {
for (let i = 0; i < depth; i++) {
if (!maybeKeys) {
maybeKeys = [];
sourceStack = [];
targetStack = [];
}
else {
for (let i = 0; i < maybeCount; i++) {
// If source and target are already being compared, consider them related with assumptions
if (maybeStack[i].get(id)) {
if (id === maybeKeys[i]) {
return Ternary.Maybe;
}
}
@ -9117,16 +9123,11 @@ namespace ts {
return Ternary.False;
}
}
else {
sourceStack = [];
targetStack = [];
maybeStack = [];
expandingFlags = 0;
}
const maybeStart = maybeCount;
maybeKeys[maybeCount] = id;
maybeCount++;
sourceStack[depth] = source;
targetStack[depth] = target;
maybeStack[depth] = createMap<RelationComparisonResult>();
maybeStack[depth].set(id, RelationComparisonResult.Succeeded);
depth++;
const saveExpandingFlags = expandingFlags;
if (!(expandingFlags & 1) && isDeeplyNestedType(source, sourceStack, depth)) expandingFlags |= 1;
@ -9135,15 +9136,19 @@ namespace ts {
expandingFlags = saveExpandingFlags;
depth--;
if (result) {
const maybeCache = maybeStack[depth];
// If result is definitely true, copy assumptions to global cache, else copy to next level up
const destinationCache = (result === Ternary.True || depth === 0) ? relation : maybeStack[depth - 1];
copyEntries(maybeCache, destinationCache);
if (result === Ternary.True || depth === 0) {
// If result is definitely true, record all maybe keys as having succeeded
for (let i = maybeStart; i < maybeCount; i++) {
relation.set(maybeKeys[i], RelationComparisonResult.Succeeded);
}
maybeCount = maybeStart;
}
}
else {
// A false result goes straight into global cache (when something is false under assumptions it
// will also be false without assumptions)
// A false result goes straight into global cache (when something is false under
// assumptions it will also be false without assumptions)
relation.set(id, reportErrors ? RelationComparisonResult.FailedAndReported : RelationComparisonResult.Failed);
maybeCount = maybeStart;
}
return result;
}