@@ -10097,22 +10097,11 @@ namespace ts {
10097
10097
}
10098
10098
10099
10099
function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
10100
- let sourceStack: Type[];
10101
- let targetStack: Type[];
10102
- let depth = 0;
10100
+ let symbolStack: Symbol[];
10101
+ let visited: Map<boolean>;
10103
10102
let inferiority = 0;
10104
- const visited = createMap<boolean>();
10105
10103
inferFromTypes(originalSource, originalTarget);
10106
10104
10107
- function isInProcess(source: Type, target: Type) {
10108
- for (let i = 0; i < depth; i++) {
10109
- if (source === sourceStack[i] && target === targetStack[i]) {
10110
- return true;
10111
- }
10112
- }
10113
- return false;
10114
- }
10115
-
10116
10105
function inferFromTypes(source: Type, target: Type) {
10117
10106
if (!couldContainTypeVariables(target)) {
10118
10107
return;
@@ -10240,26 +10229,29 @@ namespace ts {
10240
10229
else {
10241
10230
source = getApparentType(source);
10242
10231
if (source.flags & TypeFlags.Object) {
10243
- if (isInProcess(source, target)) {
10244
- return;
10245
- }
10246
- if (isDeeplyNestedType(source, sourceStack, depth) && isDeeplyNestedType(target, targetStack, depth)) {
10247
- return;
10248
- }
10249
10232
const key = source.id + "," + target.id;
10250
- if (visited.get(key)) {
10233
+ if (visited && visited .get(key)) {
10251
10234
return;
10252
10235
}
10253
- visited.set(key, true);
10254
- if (depth === 0) {
10255
- sourceStack = [];
10256
- targetStack = [];
10236
+ (visited || (visited = createMap<boolean>())).set(key, true);
10237
+ // If we are already processing another target type with the same associated symbol (such as
10238
+ // an instantiation of the same generic type), we do not explore this target as it would yield
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();
10251
+ }
10252
+ else {
10253
+ inferFromObjectTypes(source, target);
10257
10254
}
10258
- sourceStack[depth] = source;
10259
- targetStack[depth] = target;
10260
- depth++;
10261
- inferFromObjectTypes(source, target);
10262
- depth--;
10263
10255
}
10264
10256
}
10265
10257
}
0 commit comments