@@ -7921,10 +7921,10 @@ namespace ts {
7921
7921
function getInferenceMapper(context: InferenceContext): TypeMapper {
7922
7922
if (!context.mapper) {
7923
7923
const mapper: TypeMapper = t => {
7924
- const typeParameters = context.signature.typeParameters ;
7925
- for (let i = 0; i < typeParameters .length; i++) {
7926
- if (t === typeParameters [i]) {
7927
- context. inferences[i].isFixed = true;
7924
+ const inferences = context.inferences ;
7925
+ for (let i = 0; i < inferences .length; i++) {
7926
+ if (t === inferences [i].typeParameter ) {
7927
+ inferences[i].isFixed = true;
7928
7928
return getInferredType(context, i);
7929
7929
}
7930
7930
}
@@ -10131,22 +10131,22 @@ namespace ts {
10131
10131
}
10132
10132
10133
10133
function createInferenceContext(signature: Signature, inferUnionTypes: boolean, useAnyForNoInferences: boolean): InferenceContext {
10134
- const inferences = map(signature.typeParameters, createTypeInferencesObject);
10135
10134
return {
10136
10135
signature,
10136
+ inferences: map(signature.typeParameters, createInferenceInfo),
10137
10137
inferUnionTypes,
10138
- inferences,
10139
- inferredTypes: new Array(signature.typeParameters.length),
10140
10138
useAnyForNoInferences
10141
10139
};
10142
10140
}
10143
10141
10144
- function createTypeInferencesObject( ): TypeInferences {
10142
+ function createInferenceInfo(typeParameter: TypeParameter ): InferenceInfo {
10145
10143
return {
10146
- primary: undefined,
10147
- secondary: undefined,
10144
+ typeParameter,
10145
+ candidates: undefined,
10146
+ inferredType: undefined,
10147
+ priority: undefined,
10148
10148
topLevel: true,
10149
- isFixed: false,
10149
+ isFixed: false
10150
10150
};
10151
10151
}
10152
10152
@@ -10183,10 +10183,9 @@ namespace ts {
10183
10183
if (properties.length === 0 && !indexInfo) {
10184
10184
return undefined;
10185
10185
}
10186
- const typeVariable = <TypeVariable>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
10187
- const typeVariableArray = [typeVariable];
10188
- const typeInferences = createTypeInferencesObject();
10189
- const typeInferencesArray = [typeInferences];
10186
+ const typeParameter = <TypeParameter>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
10187
+ const inference = createInferenceInfo(typeParameter);
10188
+ const inferences = [inference];
10190
10189
const templateType = getTemplateTypeFromMappedType(target);
10191
10190
const readonlyMask = target.declaration.readonlyToken ? false : true;
10192
10191
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
@@ -10212,22 +10211,20 @@ namespace ts {
10212
10211
return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined);
10213
10212
10214
10213
function inferTargetType(sourceType: Type): Type {
10215
- typeInferences.primary = undefined;
10216
- typeInferences.secondary = undefined;
10217
- inferTypes(typeVariableArray, typeInferencesArray, sourceType, templateType);
10218
- const inferences = typeInferences.primary || typeInferences.secondary;
10219
- return inferences && getUnionType(inferences, /*subtypeReduction*/ true);
10214
+ inference.candidates = undefined;
10215
+ inferTypes(inferences, sourceType, templateType);
10216
+ return inference.candidates && getUnionType(inference.candidates, /*subtypeReduction*/ true);
10220
10217
}
10221
10218
}
10222
10219
10223
10220
function inferTypesWithContext(context: InferenceContext, originalSource: Type, originalTarget: Type) {
10224
- inferTypes(context.signature.typeParameters, context. inferences, originalSource, originalTarget);
10221
+ inferTypes(context.inferences, originalSource, originalTarget);
10225
10222
}
10226
10223
10227
- function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences [], originalSource: Type, originalTarget: Type) {
10224
+ function inferTypes(inferences: InferenceInfo [], originalSource: Type, originalTarget: Type) {
10228
10225
let symbolStack: Symbol[];
10229
10226
let visited: Map<boolean>;
10230
- let inferiority = 0;
10227
+ let priority = 0;
10231
10228
inferFromTypes(originalSource, originalTarget);
10232
10229
10233
10230
function inferFromTypes(source: Type, target: Type) {
@@ -10291,24 +10288,24 @@ namespace ts {
10291
10288
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
10292
10289
return;
10293
10290
}
10294
- for (let i = 0; i < typeVariables.length; i++) {
10295
- if (target === typeVariables[i]) {
10296
- const inferences = typeInferences[i];
10297
- if (!inferences.isFixed) {
10291
+ for (const inference of inferences) {
10292
+ if (target === inference.typeParameter) {
10293
+ if (!inference.isFixed) {
10298
10294
// Any inferences that are made to a type parameter in a union type are inferior
10299
10295
// to inferences made to a flat (non-union) type. This is because if we infer to
10300
10296
// T | string[], we really don't know if we should be inferring to T or not (because
10301
10297
// the correct constituent on the target side could be string[]). Therefore, we put
10302
10298
// such inferior inferences into a secondary bucket, and only use them if the primary
10303
10299
// bucket is empty.
10304
- const candidates = inferiority ?
10305
- inferences.secondary || (inferences.secondary = []) :
10306
- inferences.primary || (inferences.primary = []);
10307
- if (!contains(candidates, source)) {
10308
- candidates.push(source);
10300
+ if (!inference.candidates || priority < inference.priority) {
10301
+ inference.candidates = [source];
10302
+ inference.priority = priority;
10303
+ }
10304
+ else if (priority === inference.priority) {
10305
+ inference.candidates.push(source);
10309
10306
}
10310
10307
if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
10311
- inferences .topLevel = false;
10308
+ inference .topLevel = false;
10312
10309
}
10313
10310
}
10314
10311
return;
@@ -10330,7 +10327,7 @@ namespace ts {
10330
10327
let typeVariable: TypeVariable;
10331
10328
// First infer to each type in union or intersection that isn't a type variable
10332
10329
for (const t of targetTypes) {
10333
- if (t.flags & TypeFlags.TypeVariable && contains(typeVariables, t)) {
10330
+ if (getInferenceInfoForType( t)) {
10334
10331
typeVariable = <TypeVariable>t;
10335
10332
typeVariableCount++;
10336
10333
}
@@ -10342,9 +10339,10 @@ namespace ts {
10342
10339
// variable. This gives meaningful results for union types in co-variant positions and intersection
10343
10340
// types in contra-variant positions (such as callback parameters).
10344
10341
if (typeVariableCount === 1) {
10345
- inferiority++;
10342
+ const savePriority = priority;
10343
+ priority |= InferencePriority.NakedTypeVariable;
10346
10344
inferFromTypes(source, typeVariable);
10347
- inferiority-- ;
10345
+ priority = savePriority ;
10348
10346
}
10349
10347
}
10350
10348
else if (source.flags & TypeFlags.UnionOrIntersection) {
@@ -10384,6 +10382,17 @@ namespace ts {
10384
10382
}
10385
10383
}
10386
10384
10385
+ function getInferenceInfoForType(type: Type) {
10386
+ if (type.flags & TypeFlags.TypeVariable) {
10387
+ for (const inference of inferences) {
10388
+ if (type === inference.typeParameter) {
10389
+ return inference;
10390
+ }
10391
+ }
10392
+ }
10393
+ return undefined;
10394
+ }
10395
+
10387
10396
function inferFromObjectTypes(source: Type, target: Type) {
10388
10397
if (getObjectFlags(target) & ObjectFlags.Mapped) {
10389
10398
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
@@ -10392,13 +10401,14 @@ namespace ts {
10392
10401
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
10393
10402
// type and then make a secondary inference from that type to T. We make a secondary inference
10394
10403
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
10395
- const index = indexOf(typeVariables, (<IndexType>constraintType).type);
10396
- if (index >= 0 && !typeInferences[index] .isFixed) {
10404
+ const inference = getInferenceInfoForType( (<IndexType>constraintType).type);
10405
+ if (inference && !inference .isFixed) {
10397
10406
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
10398
10407
if (inferredType) {
10399
- inferiority++;
10400
- inferFromTypes(inferredType, typeVariables[index]);
10401
- inferiority--;
10408
+ const savePriority = priority;
10409
+ priority |= InferencePriority.MappedType;
10410
+ inferFromTypes(inferredType, inference.typeParameter);
10411
+ priority = savePriority;
10402
10412
}
10403
10413
}
10404
10414
return;
@@ -10497,33 +10507,29 @@ namespace ts {
10497
10507
return type.flags & TypeFlags.Union ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes);
10498
10508
}
10499
10509
10500
- function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
10501
- const inferences = context.inferences[index];
10502
- return inferences.primary || inferences.secondary || emptyArray;
10503
- }
10504
-
10505
10510
function hasPrimitiveConstraint(type: TypeParameter): boolean {
10506
10511
const constraint = getConstraintOfTypeParameter(type);
10507
10512
return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
10508
10513
}
10509
10514
10510
10515
function getInferredType(context: InferenceContext, index: number): Type {
10511
- let inferredType = context.inferredTypes[index];
10516
+ const inference = context.inferences[index];
10517
+ let inferredType = inference.inferredType;
10512
10518
let inferenceSucceeded: boolean;
10513
10519
if (!inferredType) {
10514
- const inferences = getInferenceCandidates(context, index) ;
10515
- if (inferences.length ) {
10520
+ const candidates = inference.candidates ;
10521
+ if (candidates ) {
10516
10522
// We widen inferred literal types if
10517
10523
// all inferences were made to top-level ocurrences of the type parameter, and
10518
10524
// the type parameter has no constraint or its constraint includes no primitive or literal types, and
10519
10525
// the type parameter was fixed during inference or does not occur at top-level in the return type.
10520
10526
const signature = context.signature;
10521
- const widenLiteralTypes = context.inferences[index] .topLevel &&
10522
- !hasPrimitiveConstraint(signature.typeParameters[index] ) &&
10523
- (context.inferences[index]. isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index] ));
10524
- const baseInferences = widenLiteralTypes ? sameMap(inferences , getWidenedLiteralType) : inferences ;
10527
+ const widenLiteralTypes = inference .topLevel &&
10528
+ !hasPrimitiveConstraint(inference.typeParameter ) &&
10529
+ (inference. isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter ));
10530
+ const baseCandidates = widenLiteralTypes ? sameMap(candidates , getWidenedLiteralType) : candidates ;
10525
10531
// Infer widened union or supertype, or the unknown type for no common supertype
10526
- const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences , /*subtypeReduction*/ true) : getCommonSupertype(baseInferences );
10532
+ const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseCandidates , /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates );
10527
10533
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
10528
10534
inferenceSucceeded = !!unionOrSuperType;
10529
10535
}
@@ -10533,7 +10539,7 @@ namespace ts {
10533
10539
// succeeds, meaning there is no error for not having inference candidates. An
10534
10540
// inference error only occurs when there are *conflicting* candidates, i.e.
10535
10541
// candidates with no common supertype.
10536
- const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index] );
10542
+ const defaultType = getDefaultFromTypeParameter(inference.typeParameter );
10537
10543
if (defaultType) {
10538
10544
// Instantiate the default type. Any forward reference to a type
10539
10545
// parameter should be instantiated to the empty object type.
@@ -10548,15 +10554,15 @@ namespace ts {
10548
10554
10549
10555
inferenceSucceeded = true;
10550
10556
}
10551
- context.inferredTypes[index] = inferredType;
10557
+ inference.inferredType = inferredType;
10552
10558
10553
10559
// Only do the constraint check if inference succeeded (to prevent cascading errors)
10554
10560
if (inferenceSucceeded) {
10555
10561
const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]);
10556
10562
if (constraint) {
10557
10563
const instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context));
10558
10564
if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
10559
- context.inferredTypes[index] = inferredType = instantiatedConstraint;
10565
+ inference.inferredType = inferredType = instantiatedConstraint;
10560
10566
}
10561
10567
}
10562
10568
}
@@ -10571,10 +10577,11 @@ namespace ts {
10571
10577
}
10572
10578
10573
10579
function getInferredTypes(context: InferenceContext): Type[] {
10574
- for (let i = 0; i < context.inferredTypes.length; i++) {
10575
- getInferredType(context, i);
10580
+ let result = [];
10581
+ for (let i = 0; i < context.inferences.length; i++) {
10582
+ result.push(getInferredType(context, i));
10576
10583
}
10577
- return context.inferredTypes ;
10584
+ return result ;
10578
10585
}
10579
10586
10580
10587
// EXPRESSION TYPE CHECKING
@@ -14837,18 +14844,18 @@ namespace ts {
14837
14844
return getSignatureInstantiation(signature, getInferredTypes(context));
14838
14845
}
14839
14846
14840
- function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
14841
- const typeParameters = signature.typeParameters ;
14847
+ function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): Type[] {
14848
+ const inferences = context.inferences ;
14842
14849
const inferenceMapper = getInferenceMapper(context);
14843
14850
14844
14851
// Clear out all the inference results from the last time inferTypeArguments was called on this context
14845
- for (let i = 0; i < typeParameters .length; i++) {
14852
+ for (let i = 0; i < inferences .length; i++) {
14846
14853
// As an optimization, we don't have to clear (and later recompute) inferred types
14847
14854
// for type parameters that have already been fixed on the previous call to inferTypeArguments.
14848
14855
// It would be just as correct to reset all of them. But then we'd be repeating the same work
14849
14856
// for the type parameters that were fixed, namely the work done by getInferredType.
14850
- if (!context. inferences[i].isFixed) {
14851
- context.inferredTypes [i] = undefined;
14857
+ if (!inferences[i].isFixed) {
14858
+ inferences [i].inferredType = undefined;
14852
14859
}
14853
14860
}
14854
14861
@@ -14908,8 +14915,7 @@ namespace ts {
14908
14915
}
14909
14916
}
14910
14917
}
14911
-
14912
- getInferredTypes(context);
14918
+ return getInferredTypes(context);
14913
14919
}
14914
14920
14915
14921
function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean {
@@ -15491,7 +15497,7 @@ namespace ts {
15491
15497
else {
15492
15498
Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
15493
15499
const failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
15494
- const inferenceCandidates = getInferenceCandidates( resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex) ;
15500
+ const inferenceCandidates = resultOfFailedInference.inferences[ resultOfFailedInference.failedTypeParameterIndex].candidates ;
15495
15501
15496
15502
let diagnosticChainHead = chainDiagnosticMessages(/*details*/ undefined, // details will be provided by call to reportNoCommonSupertypeError
15497
15503
Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
@@ -15576,8 +15582,7 @@ namespace ts {
15576
15582
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false);
15577
15583
}
15578
15584
else {
15579
- inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
15580
- typeArgumentTypes = inferenceContext.inferredTypes;
15585
+ typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
15581
15586
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
15582
15587
}
15583
15588
if (!typeArgumentsAreValid) {
0 commit comments