@@ -15564,7 +15564,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15564
15564
return undefined;
15565
15565
}
15566
15566
15567
- function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature {
15567
+ function getSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature {
15568
15568
const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript));
15569
15569
if (inferredTypeParameters) {
15570
15570
const returnSignature = getSingleCallOrConstructSignature(getReturnTypeOfSignature(instantiatedSignature));
@@ -15628,6 +15628,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15628
15628
);
15629
15629
}
15630
15630
15631
+ function getImplementationSignature(signature: Signature) {
15632
+ return signature.typeParameters ?
15633
+ signature.implementationSignatureCache ||= createImplementationSignature(signature) :
15634
+ signature;
15635
+ }
15636
+
15637
+ function createImplementationSignature(signature: Signature) {
15638
+ return signature.typeParameters ? instantiateSignature(signature, createTypeMapper([], [])) : signature;
15639
+ }
15640
+
15631
15641
function getBaseSignature(signature: Signature) {
15632
15642
const typeParameters = signature.typeParameters;
15633
15643
if (typeParameters) {
@@ -15663,7 +15673,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15663
15673
// The type must have a symbol with a `Function` flag and a declaration in order to be correctly flagged as possibly containing
15664
15674
// type variables by `couldContainTypeVariables`
15665
15675
const type = createObjectType(ObjectFlags.Anonymous | ObjectFlags.SingleSignatureType, createSymbol(SymbolFlags.Function, InternalSymbolName.Function)) as SingleSignatureType;
15666
- if (signature.declaration) {
15676
+ if (signature.declaration && !nodeIsSynthesized(signature.declaration)) { // skip synthetic declarations - keeping those around could be bad, since they lack a parent pointer
15667
15677
type.symbol.declarations = [signature.declaration];
15668
15678
type.symbol.valueDeclaration = signature.declaration;
15669
15679
}
@@ -25139,6 +25149,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25139
25149
const result = !!(type.flags & TypeFlags.Instantiable ||
25140
25150
type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && (
25141
25151
objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || some(getTypeArguments(type as TypeReference), couldContainTypeVariables)) ||
25152
+ objectFlags & ObjectFlags.SingleSignatureType && !!length((type as SingleSignatureType).outerTypeParameters) ||
25142
25153
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
25143
25154
objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType)
25144
25155
) ||
@@ -26372,25 +26383,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26372
26383
// inference error only occurs when there are *conflicting* candidates, i.e.
26373
26384
// candidates with no common supertype.
26374
26385
const defaultType = getDefaultFromTypeParameter(inference.typeParameter);
26375
- inferredType = defaultType;
26386
+ // Instantiate the default type. Any forward reference to a type
26387
+ // parameter should be instantiated to the empty object type.
26388
+ inferredType = instantiateType(defaultType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
26376
26389
}
26377
26390
}
26378
26391
else {
26379
26392
inferredType = getTypeFromInference(inference);
26380
26393
}
26381
26394
26382
- const isDefault = !inferredType;
26383
- inferredType ||= getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault));
26384
- inference.inferredType = inferredType;
26385
- // Instantiate the inferred type. Any forward reference to a type
26386
- // parameter should be instantiated to the empty object type.
26387
- inferredType = instantiateType(inferredType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
26388
- inference.inferredType = inferredType;
26395
+ inference.inferredType = inferredType || getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault));
26389
26396
26390
26397
const constraint = getConstraintOfTypeParameter(inference.typeParameter);
26391
26398
if (constraint) {
26392
26399
const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
26393
- if (isDefault || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
26400
+ if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
26394
26401
// If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint.
26395
26402
inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
26396
26403
}
@@ -34875,7 +34882,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34875
34882
}
34876
34883
34877
34884
for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
34878
- const candidate = candidates[candidateIndex];
34885
+ let candidate = candidates[candidateIndex];
34879
34886
if (!hasCorrectTypeArgumentArity(candidate, typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
34880
34887
continue;
34881
34888
}
@@ -34884,7 +34891,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34884
34891
let inferenceContext: InferenceContext | undefined;
34885
34892
34886
34893
if (candidate.typeParameters) {
34887
- let typeArgumentTypes: Type[] | undefined;
34894
+ // If we are *inside the body of candidate*, we need to create a clone of `candidate` with differing type parameter identities,
34895
+ // so our inference results for this call doesn't pollute expression types referencing the outer type parameter!
34896
+ if (candidate.declaration && findAncestor(node, a => a === candidate.declaration)) {
34897
+ candidate = getImplementationSignature(candidate);
34898
+ }
34899
+ let typeArgumentTypes: readonly Type[] | undefined;
34888
34900
if (some(typeArguments)) {
34889
34901
typeArgumentTypes = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
34890
34902
if (!typeArgumentTypes) {
@@ -34893,8 +34905,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34893
34905
}
34894
34906
}
34895
34907
else {
34896
- inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
34897
- typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext);
34908
+ inferenceContext = createInferenceContext(candidate.typeParameters!, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
34909
+ // The resulting type arguments are instantiated with the inference context mapper, as the inferred types may still contain references to the inference context's
34910
+ // type variables via contextual projection. These are kept generic until all inferences are locked in, so the dependencies expressed can pass constraint checks.
34911
+ typeArgumentTypes = instantiateTypes(inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext), inferenceContext.nonFixingMapper);
34898
34912
argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal;
34899
34913
}
34900
34914
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
@@ -34919,7 +34933,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34919
34933
// round of type inference and applicability checking for this particular candidate.
34920
34934
argCheckMode = CheckMode.Normal;
34921
34935
if (inferenceContext) {
34922
- const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext);
34936
+ const typeArgumentTypes = instantiateTypes( inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext), inferenceContext.mapper );
34923
34937
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters);
34924
34938
// If the original signature has a generic rest type, instantiation may produce a
34925
34939
// signature with different arity and we need to perform another arity check.
0 commit comments