@@ -10096,21 +10096,29 @@ namespace ts {
10096
10096
inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget);
10097
10097
}
10098
10098
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
+
10099
10105
function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
10100
- let sourceStack: Type[];
10101
- let targetStack: Type[];
10106
+ let stack: Type[];
10102
10107
let depth = 0;
10103
10108
let inferiority = 0;
10104
10109
const visited = createMap<boolean>();
10105
10110
inferFromTypes(originalSource, originalTarget);
10106
10111
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;
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
+ }
10111
10120
}
10112
10121
}
10113
- return false;
10114
10122
}
10115
10123
10116
10124
function inferFromTypes(source: Type, target: Type) {
@@ -10240,23 +10248,18 @@ namespace ts {
10240
10248
else {
10241
10249
source = getApparentType(source);
10242
10250
if (source.flags & TypeFlags.Object) {
10243
- if (isInProcess(source, target)) {
10244
- return;
10245
- }
10246
- if (isDeeplyNestedType(source, sourceStack, depth) && isDeeplyNestedType( target, targetStack, depth )) {
10251
+ // If we are already processing another target type with the same associated symbol (such as
10252
+ // 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)) {
10247
10255
return;
10248
10256
}
10249
10257
const key = source.id + "," + target.id;
10250
10258
if (visited.get(key)) {
10251
10259
return;
10252
10260
}
10253
10261
visited.set(key, true);
10254
- if (depth === 0) {
10255
- sourceStack = [];
10256
- targetStack = [];
10257
- }
10258
- sourceStack[depth] = source;
10259
- targetStack[depth] = target;
10262
+ (stack || (stack = []))[depth] = target;
10260
10263
depth++;
10261
10264
inferFromObjectTypes(source, target);
10262
10265
depth--;
0 commit comments