@@ -1487,6 +1487,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
14871487 var lastGetCombinedModifierFlagsNode: Declaration | undefined;
14881488 var lastGetCombinedModifierFlagsResult = ModifierFlags.None;
14891489
1490+ var chooseOverloadRecursionLevel = -1; // #56013
1491+ var chooseOverloadFlushNodesSignaturesReq: (Set<Node> | undefined)[] = []; // #56013
1492+
14901493 // for public members that accept a Node or one of its subtypes, we must guard against
14911494 // synthetic nodes created during transformations by calling `getParseTreeNode`.
14921495 // for most of these, we perform the guard only on `checker` to avoid any possible
@@ -34310,87 +34313,95 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3431034313 }
3431134314
3431234315 function chooseOverload(candidates: Signature[], relation: Map<string, RelationComparisonResult>, isSingleNonGenericCandidate: boolean, signatureHelpTrailingComma = false) {
34313- candidatesForArgumentError = undefined;
34314- candidateForArgumentArityError = undefined;
34315- candidateForTypeArgumentError = undefined;
34316-
34317- if (isSingleNonGenericCandidate) {
34318- const candidate = candidates[0];
34319- if (some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
34320- return undefined;
34321- }
34322- if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
34323- candidatesForArgumentError = [candidate];
34324- return undefined;
34316+ chooseOverloadRecursionLevel++; // #56013
34317+ chooseOverloadFlushNodesSignaturesReq[chooseOverloadRecursionLevel] = undefined;
34318+ const result = (() => {
34319+ candidatesForArgumentError = undefined;
34320+ candidateForArgumentArityError = undefined;
34321+ candidateForTypeArgumentError = undefined;
34322+
34323+ if (isSingleNonGenericCandidate) {
34324+ const candidate = candidates[0];
34325+ if (some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
34326+ return undefined;
34327+ }
34328+ if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
34329+ candidatesForArgumentError = [candidate];
34330+ return undefined;
34331+ }
34332+ return candidate;
3432534333 }
34326- return candidate;
34327- }
3432834334
34329- for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
34330- const candidate = candidates[candidateIndex];
34331- if (!hasCorrectTypeArgumentArity(candidate, typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
34332- continue;
34333- }
34335+ for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
34336+ if (candidateIndex > 0) chooseOverloadFlushNodesSignaturesReq[chooseOverloadRecursionLevel] = new Set(); // #56013
34337+ const candidate = candidates[candidateIndex];
34338+ if (!hasCorrectTypeArgumentArity(candidate, typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
34339+ continue;
34340+ }
3433434341
34335- let checkCandidate: Signature;
34336- let inferenceContext: InferenceContext | undefined;
34342+ let checkCandidate: Signature;
34343+ let inferenceContext: InferenceContext | undefined;
3433734344
34338- if (candidate.typeParameters) {
34339- let typeArgumentTypes: Type[] | undefined;
34340- if (some(typeArguments)) {
34341- typeArgumentTypes = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
34342- if (!typeArgumentTypes) {
34343- candidateForTypeArgumentError = candidate;
34344- continue;
34345+ if (candidate.typeParameters) {
34346+ let typeArgumentTypes: Type[] | undefined;
34347+ if (some(typeArguments)) {
34348+ typeArgumentTypes = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
34349+ if (!typeArgumentTypes) {
34350+ candidateForTypeArgumentError = candidate;
34351+ continue;
34352+ }
3434534353 }
34346- }
34347- else {
34348- inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
34349- typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext);
34350- argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal;
34351- }
34352- checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
34353- // If the original signature has a generic rest type, instantiation may produce a
34354- // signature with different arity and we need to perform another arity check.
34355- if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
34356- candidateForArgumentArityError = checkCandidate;
34357- continue;
34358- }
34359- }
34360- else {
34361- checkCandidate = candidate;
34362- }
34363- if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
34364- // Give preference to error candidates that have no rest parameters (as they are more specific)
34365- (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
34366- continue;
34367- }
34368- if (argCheckMode) {
34369- // If one or more context sensitive arguments were excluded, we start including
34370- // them now (and keeping do so for any subsequent candidates) and perform a second
34371- // round of type inference and applicability checking for this particular candidate.
34372- argCheckMode = CheckMode.Normal;
34373- if (inferenceContext) {
34374- const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext);
34375- checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters);
34354+ else {
34355+ inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
34356+ typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext);
34357+ argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal;
34358+ }
34359+ checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
3437634360 // If the original signature has a generic rest type, instantiation may produce a
3437734361 // signature with different arity and we need to perform another arity check.
3437834362 if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
3437934363 candidateForArgumentArityError = checkCandidate;
3438034364 continue;
3438134365 }
3438234366 }
34367+ else {
34368+ checkCandidate = candidate;
34369+ }
3438334370 if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
3438434371 // Give preference to error candidates that have no rest parameters (as they are more specific)
3438534372 (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
3438634373 continue;
3438734374 }
34375+ if (argCheckMode) {
34376+ // If one or more context sensitive arguments were excluded, we start including
34377+ // them now (and keeping do so for any subsequent candidates) and perform a second
34378+ // round of type inference and applicability checking for this particular candidate.
34379+ argCheckMode = CheckMode.Normal;
34380+ if (inferenceContext) {
34381+ const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext);
34382+ checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters);
34383+ // If the original signature has a generic rest type, instantiation may produce a
34384+ // signature with different arity and we need to perform another arity check.
34385+ if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
34386+ candidateForArgumentArityError = checkCandidate;
34387+ continue;
34388+ }
34389+ }
34390+ if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
34391+ // Give preference to error candidates that have no rest parameters (as they are more specific)
34392+ (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
34393+ continue;
34394+ }
34395+ }
34396+ candidates[candidateIndex] = checkCandidate;
34397+ return checkCandidate;
3438834398 }
34389- candidates[candidateIndex] = checkCandidate;
34390- return checkCandidate;
34391- }
3439234399
34393- return undefined;
34400+ return undefined;
34401+ })();
34402+ chooseOverloadFlushNodesSignaturesReq[chooseOverloadRecursionLevel] = undefined;
34403+ chooseOverloadRecursionLevel--;
34404+ return result;
3439434405 }
3439534406 }
3439634407
@@ -35292,7 +35303,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3529235303 checkGrammarTypeArguments(node, node.typeArguments);
3529335304
3529435305 const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode);
35295- if (signature === resolvingSignature) {
35306+ if (signature === resolvingSignature || !signature /* #56013 */ ) {
3529635307 // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that
3529735308 // returns a function type. We defer checking and return silentNeverType.
3529835309 return silentNeverType;
@@ -35361,6 +35372,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3536135372 }
3536235373
3536335374 function checkDeprecatedSignature(signature: Signature, node: CallLikeExpression) {
35375+ Debug.assert(signature);
3536435376 if (signature.flags & SignatureFlags.IsSignatureCandidateForOverloadFailure) return;
3536535377 if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) {
3536635378 const suggestionNode = getDeprecatedSuggestionNode(node);
@@ -38932,6 +38944,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3893238944 const saveCurrentNode = currentNode;
3893338945 currentNode = node;
3893438946 instantiationCount = 0;
38947+ // #56013
38948+ if (node.kind === SyntaxKind.CallExpression && chooseOverloadRecursionLevel >= 0) {
38949+ let setOfNode: Set<Node> | undefined;
38950+ if (chooseOverloadRecursionLevel >= 0 && (setOfNode = chooseOverloadFlushNodesSignaturesReq[chooseOverloadRecursionLevel])) {
38951+ if (!setOfNode.has(node)) {
38952+ getNodeLinks(node).resolvedSignature = undefined;
38953+ setOfNode.add(node);
38954+ }
38955+ }
38956+ }
3893538957 const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
3893638958 const type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
3893738959 if (isConstEnumObjectType(type)) {
0 commit comments