Skip to content

Commit ed1a6c1

Browse files
committed
Address CR feedback + defer creation of visited map
1 parent e9ccb16 commit ed1a6c1

File tree

1 file changed

+21
-32
lines changed

1 file changed

+21
-32
lines changed

src/compiler/checker.ts

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10096,31 +10096,12 @@ namespace ts {
1009610096
inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget);
1009710097
}
1009810098

10099-
function getSymbolForInference(type: Type) {
10100-
// Exclude the static side of classes since it shares its symbol with the instance side which leads
10101-
// to false positives.
10102-
return type.flags & TypeFlags.Object && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class) ? type.symbol : undefined;
10103-
}
10104-
1010510099
function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
10106-
let stack: Type[];
10107-
let depth = 0;
10100+
let symbolStack: Symbol[];
10101+
let visited: Map<boolean>;
1010810102
let inferiority = 0;
10109-
const visited = createMap<boolean>();
1011010103
inferFromTypes(originalSource, originalTarget);
1011110104

10112-
function isInstantiationInProcess(type: Type) {
10113-
const symbol = getSymbolForInference(type);
10114-
if (symbol) {
10115-
for (let i = 0; i < depth; i++) {
10116-
const t = stack[i];
10117-
if (getSymbolForInference(t) === symbol) {
10118-
return true;
10119-
}
10120-
}
10121-
}
10122-
}
10123-
1012410105
function inferFromTypes(source: Type, target: Type) {
1012510106
if (!couldContainTypeVariables(target)) {
1012610107
return;
@@ -10248,21 +10229,29 @@ namespace ts {
1024810229
else {
1024910230
source = getApparentType(source);
1025010231
if (source.flags & TypeFlags.Object) {
10232+
const key = source.id + "," + target.id;
10233+
if (visited && visited.get(key)) {
10234+
return;
10235+
}
10236+
(visited || (visited = createMap<boolean>())).set(key, true);
1025110237
// If we are already processing another target type with the same associated symbol (such as
1025210238
// an instantiation of the same generic type), we do not explore this target as it would yield
10253-
// no further inferences.
10254-
if (isInstantiationInProcess(target)) {
10255-
return;
10239+
// no further inferences. We exclude the static side of classes from this check since it shares
10240+
// its symbol with the instance side which would lead to false positives.
10241+
const isNonConstructorObject = target.flags & TypeFlags.Object &&
10242+
!(getObjectFlags(target) & ObjectFlags.Anonymous && target.symbol && target.symbol.flags & SymbolFlags.Class);
10243+
const symbol = isNonConstructorObject ? target.symbol : undefined;
10244+
if (symbol) {
10245+
if (contains(symbolStack, symbol)) {
10246+
return;
10247+
}
10248+
(symbolStack || (symbolStack = [])).push(symbol);
10249+
inferFromObjectTypes(source, target);
10250+
symbolStack.pop();
1025610251
}
10257-
const key = source.id + "," + target.id;
10258-
if (visited.get(key)) {
10259-
return;
10252+
else {
10253+
inferFromObjectTypes(source, target);
1026010254
}
10261-
visited.set(key, true);
10262-
(stack || (stack = []))[depth] = target;
10263-
depth++;
10264-
inferFromObjectTypes(source, target);
10265-
depth--;
1026610255
}
1026710256
}
1026810257
}

0 commit comments

Comments
 (0)