From d00ab417c6a4e5e084c3bbeab9b31ccd9fbc5854 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 15:58:54 -0700 Subject: [PATCH] checkTypeParameters now always calls fillMissingTypeArguments And refactor checkTypeParameters to be easier to use and to read. --- src/compiler/checker.ts | 61 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 56835e13dde..ff78ccaa135 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15643,34 +15643,35 @@ namespace ts { return getInferredTypes(context); } - function checkTypeArguments(signature: Signature, typeArgumentNodes: ReadonlyArray, typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean { + function checkTypeArguments(signature: Signature, typeArguments: ReadonlyArray, reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | false { + const isJavascript = isInJavaScriptFile(signature.declaration); const typeParameters = signature.typeParameters; - let typeArgumentsAreAssignable = true; + const typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); let mapper: TypeMapper; - for (let i = 0; i < typeArgumentNodes.length; i++) { - if (typeArgumentsAreAssignable /* so far */) { - const constraint = getConstraintOfTypeParameter(typeParameters[i]); - if (constraint) { - let errorInfo: DiagnosticMessageChain; - let typeArgumentHeadMessage = Diagnostics.Type_0_does_not_satisfy_the_constraint_1; - if (reportErrors && headMessage) { - errorInfo = chainDiagnosticMessages(errorInfo, typeArgumentHeadMessage); - typeArgumentHeadMessage = headMessage; - } - if (!mapper) { - mapper = createTypeMapper(typeParameters, typeArgumentTypes); - } - const typeArgument = typeArgumentTypes[i]; - typeArgumentsAreAssignable = checkTypeAssignableTo( - typeArgument, - getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument), - reportErrors ? typeArgumentNodes[i] : undefined, - typeArgumentHeadMessage, - errorInfo); + for (let i = 0; i < typeArguments.length; i++) { + const constraint = getConstraintOfTypeParameter(typeParameters[i]); + if (constraint) { + let errorInfo: DiagnosticMessageChain; + let typeArgumentHeadMessage = Diagnostics.Type_0_does_not_satisfy_the_constraint_1; + if (reportErrors && headMessage) { + errorInfo = chainDiagnosticMessages(errorInfo, typeArgumentHeadMessage); + typeArgumentHeadMessage = headMessage; + } + if (!mapper) { + mapper = createTypeMapper(typeParameters, typeArgumentTypes); + } + const typeArgument = typeArgumentTypes[i]; + if (!checkTypeAssignableTo( + typeArgument, + getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument), + reportErrors ? typeArguments[i] : undefined, + typeArgumentHeadMessage, + errorInfo)) { + return false; } } } - return typeArgumentsAreAssignable; + return typeArgumentTypes; } /** @@ -16203,10 +16204,7 @@ namespace ts { checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - const isJavascript = isInJavaScriptFile(candidateForTypeArgumentError.declaration); - const typeArguments = (node).typeArguments; - const typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidateForTypeArgumentError.typeParameters, getMinTypeArgumentCount(candidateForTypeArgumentError.typeParameters), isJavascript); - checkTypeArguments(candidateForTypeArgumentError, typeArguments, typeArgumentTypes, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { let min = Number.POSITIVE_INFINITY; @@ -16305,10 +16303,12 @@ namespace ts { candidate = originalCandidate; if (candidate.typeParameters) { let typeArgumentTypes: Type[]; - const isJavascript = isInJavaScriptFile(candidate.declaration); if (typeArguments) { - typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, getMinTypeArgumentCount(candidate.typeParameters), isJavascript); - if (!checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)) { + const typeArgumentResult = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false); + if (typeArgumentResult) { + typeArgumentTypes = typeArgumentResult; + } + else { candidateForTypeArgumentError = originalCandidate; break; } @@ -16316,6 +16316,7 @@ namespace ts { else { typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); } + const isJavascript = isInJavaScriptFile(candidate.declaration); candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript); } if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {