@@ -10169,7 +10169,7 @@ namespace ts {
10169
10169
// types rules (i.e. proper contravariance) for inferences.
10170
10170
inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
10171
10171
}
10172
- combinedMapper = combineTypeMappers(mapper, context);
10172
+ combinedMapper = combineTypeMappers(mapper, context.mapper );
10173
10173
}
10174
10174
// Instantiate the extends type including inferences for 'infer T' type parameters
10175
10175
const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
@@ -10778,8 +10778,8 @@ namespace ts {
10778
10778
return t => typeParameters.indexOf(t) >= index ? emptyObjectType : t;
10779
10779
}
10780
10780
10781
- function cloneInferenceContext(context: InferenceContext , extraFlags: InferenceFlags = 0): InferenceContext {
10782
- return createInferenceContext(context.typeParameters, context.signature, context.flags | extraFlags, context.compareTypes, context.inferences);
10781
+ function cloneInferenceContext<T extends InferenceContext | undefined> (context: T , extraFlags: InferenceFlags = 0): InferenceContext | T & undefined {
10782
+ return context && createInferenceContext(context.typeParameters, context.signature, context.flags | extraFlags, context.compareTypes, context.inferences);
10783
10783
}
10784
10784
10785
10785
function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined {
@@ -10793,10 +10793,9 @@ namespace ts {
10793
10793
inferences.push(info);
10794
10794
}
10795
10795
}
10796
- if (!params.length) {
10797
- return undefined;
10798
- }
10799
- return createInferenceContext(params, context.signature, context.flags | InferenceFlags.NoDefault, context.compareTypes, inferences);
10796
+ return params.length ?
10797
+ createInferenceContext(params, context.signature, context.flags | InferenceFlags.NoDefault, context.compareTypes, inferences) :
10798
+ undefined;
10800
10799
}
10801
10800
10802
10801
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
@@ -14303,26 +14302,31 @@ namespace ts {
14303
14302
}
14304
14303
14305
14304
function createInferenceContext(typeParameters: ReadonlyArray<TypeParameter>, signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext {
14306
- const inferences = baseInferences ? baseInferences.map(cloneInferenceInfo) : typeParameters.map(createInferenceInfo);
14307
- const context = mapper as InferenceContext;
14308
- context.typeParameters = typeParameters;
14309
- context.signature = signature;
14310
- context.inferences = inferences;
14311
- context.flags = flags;
14312
- context.compareTypes = compareTypes || compareTypesAssignable;
14305
+ const context: InferenceContext = {
14306
+ typeParameters,
14307
+ signature,
14308
+ inferences: baseInferences ? baseInferences.map(cloneInferenceInfo) : typeParameters.map(createInferenceInfo),
14309
+ flags,
14310
+ compareTypes: compareTypes || compareTypesAssignable,
14311
+ mapper: t => mapToInferredType(context, t, /*fix*/ true),
14312
+ nonFixingMapper: t => mapToInferredType(context, t, /*fix*/ false),
14313
+ };
14313
14314
return context;
14315
+ }
14314
14316
14315
- function mapper(t: Type): Type {
14316
- for (let i = 0; i < inferences.length; i++) {
14317
- if (t === inferences[i].typeParameter) {
14318
- if (!(context.flags & InferenceFlags.NoFixing)) {
14319
- inferences[i].isFixed = true;
14320
- }
14321
- return getInferredType(context, i);
14317
+ function mapToInferredType(context: InferenceContext, t: Type, fix: boolean): Type {
14318
+ const inferences = context.inferences;
14319
+ for (let i = 0; i < inferences.length; i++) {
14320
+ const inference = inferences[i];
14321
+ if (t === inference.typeParameter) {
14322
+ if (fix && !inference.isFixed) {
14323
+ inference.isFixed = true;
14324
+ inference.inferredType = undefined;
14322
14325
}
14326
+ return getInferredType(context, i);
14323
14327
}
14324
- return t;
14325
14328
}
14329
+ return t;
14326
14330
}
14327
14331
14328
14332
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
@@ -14349,6 +14353,10 @@ namespace ts {
14349
14353
};
14350
14354
}
14351
14355
14356
+ function getMapperFromContext<T extends InferenceContext | undefined>(context: T): TypeMapper | T & undefined {
14357
+ return context && context.mapper;
14358
+ }
14359
+
14352
14360
// Return true if the given type could possibly reference a type parameter for which
14353
14361
// we perform type inference (i.e. a type parameter of a generic function). We cache
14354
14362
// results for union and intersection types for performance reasons.
@@ -14591,15 +14599,18 @@ namespace ts {
14591
14599
const candidate = propagationType || source;
14592
14600
// We make contravariant inferences only if we are in a pure contravariant position,
14593
14601
// i.e. only if we have not descended into a bivariant position.
14594
- if (contravariant && !bivariant) {
14595
- inference.contraCandidates = appendIfUnique(inference.contraCandidates, candidate);
14602
+ if (contravariant && !bivariant && !contains(inference.contraCandidates, candidate)) {
14603
+ inference.contraCandidates = append(inference.contraCandidates, candidate);
14604
+ inference.inferredType = undefined;
14596
14605
}
14597
- else {
14598
- inference.candidates = appendIfUnique(inference.candidates, candidate);
14606
+ else if (!contains(inference.candidates, candidate)) {
14607
+ inference.candidates = append(inference.candidates, candidate);
14608
+ inference.inferredType = undefined;
14599
14609
}
14600
14610
}
14601
- if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
14611
+ if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
14602
14612
inference.topLevel = false;
14613
+ inference.inferredType = undefined;
14603
14614
}
14604
14615
}
14605
14616
return;
@@ -15032,7 +15043,7 @@ namespace ts {
15032
15043
inferredType = instantiateType(defaultType,
15033
15044
combineTypeMappers(
15034
15045
createBackreferenceMapper(context.typeParameters, index),
15035
- context));
15046
+ context.nonFixingMapper ));
15036
15047
}
15037
15048
else {
15038
15049
inferredType = getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault));
@@ -15047,12 +15058,10 @@ namespace ts {
15047
15058
15048
15059
const constraint = getConstraintOfTypeParameter(inference.typeParameter);
15049
15060
if (constraint) {
15050
- context.flags |= InferenceFlags.NoFixing;
15051
- const instantiatedConstraint = instantiateType(constraint, context);
15061
+ const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
15052
15062
if (!context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
15053
15063
inference.inferredType = inferredType = instantiatedConstraint;
15054
15064
}
15055
- context.flags &= ~InferenceFlags.NoFixing;
15056
15065
}
15057
15066
}
15058
15067
@@ -17525,7 +17534,7 @@ namespace ts {
17525
17534
while (type) {
17526
17535
const thisType = getThisTypeFromContextualType(type);
17527
17536
if (thisType) {
17528
- return instantiateType(thisType, getInferenceContext(containingLiteral));
17537
+ return instantiateType(thisType, getMapperFromContext( getInferenceContext(containingLiteral) ));
17529
17538
}
17530
17539
if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
17531
17540
break;
@@ -20135,7 +20144,7 @@ namespace ts {
20135
20144
// the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any')
20136
20145
// for T but leave it possible to later infer '[any]' back to A.
20137
20146
const restType = getEffectiveRestType(contextualSignature);
20138
- const mapper = inferenceContext && restType && restType.flags & TypeFlags.TypeParameter ? cloneInferenceContext( inferenceContext) : inferenceContext;
20147
+ const mapper = inferenceContext && ( restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper) ;
20139
20148
const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature;
20140
20149
forEachMatchingParameterType(sourceSignature, signature, (source, target) => {
20141
20150
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
@@ -20161,17 +20170,6 @@ namespace ts {
20161
20170
}
20162
20171
20163
20172
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray<Expression>, checkMode: CheckMode, context: InferenceContext): Type[] {
20164
- // Clear out all the inference results from the last time inferTypeArguments was called on this context
20165
- for (const inference of context.inferences) {
20166
- // As an optimization, we don't have to clear (and later recompute) inferred types
20167
- // for type parameters that have already been fixed on the previous call to inferTypeArguments.
20168
- // It would be just as correct to reset all of them. But then we'd be repeating the same work
20169
- // for the type parameters that were fixed, namely the work done by getInferredType.
20170
- if (!inference.isFixed) {
20171
- inference.inferredType = undefined;
20172
- }
20173
- }
20174
-
20175
20173
if (isJsxOpeningLikeElement(node)) {
20176
20174
return inferJsxTypeArguments(node, signature, checkMode, context);
20177
20175
}
@@ -20183,11 +20181,11 @@ namespace ts {
20183
20181
if (node.kind !== SyntaxKind.Decorator) {
20184
20182
const contextualType = getContextualType(node);
20185
20183
if (contextualType) {
20186
- // We clone the contextual mapper to avoid disturbing a resolution in progress for an
20184
+ // We clone the inference context to avoid disturbing a resolution in progress for an
20187
20185
// outer call expression. Effectively we just want a snapshot of whatever has been
20188
20186
// inferred for any outer call expression so far.
20189
- const outerContext = getInferenceContext(node);
20190
- const instantiatedType = instantiateType(contextualType, outerContext && cloneInferenceContext(outerContext, InferenceFlags.NoDefault) );
20187
+ const outerMapper = getMapperFromContext(cloneInferenceContext( getInferenceContext(node), InferenceFlags.NoDefault) );
20188
+ const instantiatedType = instantiateType(contextualType, outerMapper );
20191
20189
// If the contextual type is a generic function type with a single call signature, we
20192
20190
// instantiate the type with its own type parameters and type arguments. This ensures that
20193
20191
// the type parameters are not erased to type any during type inference such that they can
@@ -20204,7 +20202,7 @@ namespace ts {
20204
20202
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
20205
20203
// Create a type mapper for instantiating generic contextual types using the inferences made
20206
20204
// from the return type.
20207
- context.returnMapper = cloneInferredPartOfContext(context);
20205
+ context.returnMapper = getMapperFromContext( cloneInferredPartOfContext(context) );
20208
20206
}
20209
20207
}
20210
20208
@@ -21865,7 +21863,7 @@ namespace ts {
21865
21863
if (restType && restType.flags & TypeFlags.TypeParameter) {
21866
21864
// The contextual signature has a generic rest parameter. We first instantiate the contextual
21867
21865
// signature (without fixing type parameters) and assign types to contextually typed parameters.
21868
- const instantiatedContext = instantiateSignature(context, cloneInferenceContext( inferenceContext) );
21866
+ const instantiatedContext = instantiateSignature(context, inferenceContext.nonFixingMapper );
21869
21867
assignContextualParameterTypes(signature, instantiatedContext);
21870
21868
// We then infer from a tuple type representing the parameters that correspond to the contextual
21871
21869
// rest parameter.
@@ -22316,7 +22314,7 @@ namespace ts {
22316
22314
inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!);
22317
22315
}
22318
22316
const instantiatedContextualSignature = inferenceContext ?
22319
- instantiateSignature(contextualSignature, inferenceContext) : contextualSignature;
22317
+ instantiateSignature(contextualSignature, inferenceContext.mapper ) : contextualSignature;
22320
22318
assignContextualParameterTypes(signature, instantiatedContextualSignature);
22321
22319
}
22322
22320
if (!getReturnTypeFromAnnotation(node) && !signature.resolvedReturnType) {
@@ -23617,13 +23615,6 @@ namespace ts {
23617
23615
return type;
23618
23616
}
23619
23617
23620
- // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
23621
- // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
23622
- // expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in
23623
- // conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function
23624
- // object, it serves as an indicator that all contained function and arrow expressions should be considered to
23625
- // have the wildcard function type; this form of type check is used during overload resolution to exclude
23626
- // contextually typed function and arrow expressions in the initial phase.
23627
23618
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type {
23628
23619
const saveCurrentNode = currentNode;
23629
23620
currentNode = node;
0 commit comments