@@ -4615,10 +4615,18 @@ module ts {
4615
4615
if (target === typeParameters[i]) {
4616
4616
let inferences = context.inferences[i];
4617
4617
if (!inferences.isFixed) {
4618
+ // Any inferences that are made to a type parameter in a union type are inferior
4619
+ // to inferences made to a flat (non-union) type. This is because if we infer to
4620
+ // T | string[], we really don't know if we should be inferring to T or not (because
4621
+ // the correct constituent on the target side could be string[]). Therefore, we put
4622
+ // such inferior inferences into a secondary bucket, and only use them if the primary
4623
+ // bucket is empty.
4618
4624
let candidates = inferiority ?
4619
4625
inferences.secondary || (inferences.secondary = []) :
4620
4626
inferences.primary || (inferences.primary = []);
4621
- if (!contains(candidates, source)) candidates.push(source);
4627
+ if (!contains(candidates, source)) {
4628
+ candidates.push(source);
4629
+ }
4622
4630
}
4623
4631
return;
4624
4632
}
@@ -6358,12 +6366,22 @@ module ts {
6358
6366
// Clear out all the inference results from the last time inferTypeArguments was called on this context
6359
6367
for (let i = 0; i < typeParameters.length; i++) {
6360
6368
// As an optimization, we don't have to clear (and later recompute) inferred types
6361
- // for type parameters that have already been fixed on the previous call to inferTypeArguments
6369
+ // for type parameters that have already been fixed on the previous call to inferTypeArguments.
6370
+ // It would be just as correct to reset all of them. But then we'd be repeating the same work
6371
+ // for the type parameters that were fixed, namely the work done by getInferredType.
6362
6372
if (!context.inferences[i].isFixed) {
6363
6373
context.inferredTypes[i] = undefined;
6364
6374
}
6365
6375
}
6366
- if (context.failedTypeParameterIndex >= 0 && !context.inferences[context.failedTypeParameterIndex].isFixed) {
6376
+
6377
+ // On this call to inferTypeArguments, we may get more inferences for certain type parameters that were not
6378
+ // fixed last time. This means that a type parameter that failed inference last time may succeed this time,
6379
+ // or vice versa. Therefore, the failedTypeParameterIndex is useless if it points to an unfixed type parameter,
6380
+ // because it may change. So here we reset it. However, getInferredType will not revisit any type parameters
6381
+ // that were previously fixed. So if a fixed type parameter failed previously, it will fail again because
6382
+ // it will contain the exact same set of inferences. So if we reset the index from a fixed type parameter,
6383
+ // we will lose information that we won't recover this time around.
6384
+ if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) {
6367
6385
context.failedTypeParameterIndex = undefined;
6368
6386
}
6369
6387
0 commit comments