From 7a31706a9ff01cacd58ca7b5a7601940845b0439 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 30 Jan 2019 06:38:13 -0800 Subject: [PATCH] Only check constraints after type argument inference is complete --- src/compiler/checker.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ed65908d926..44f118b3a54 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14788,7 +14788,7 @@ namespace ts { return getWidenedType(unwidenedType); } - function getInferredType(context: InferenceContext, index: number): Type { + function getInferredType(context: InferenceContext, index: number, ignoreConstraints = false): Type { const inference = context.inferences[index]; let inferredType = inference.inferredType; if (!inferredType) { @@ -14836,11 +14836,13 @@ namespace ts { inference.inferredType = inferredType; - const constraint = getConstraintOfTypeParameter(inference.typeParameter); - if (constraint) { - const instantiatedConstraint = instantiateType(constraint, context); - if (!context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { - inference.inferredType = inferredType = instantiatedConstraint; + if (!ignoreConstraints) { + const constraint = getConstraintOfTypeParameter(inference.typeParameter); + if (constraint) { + const instantiatedConstraint = instantiateType(constraint, context); + if (!context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { + inference.inferredType = inferredType = instantiatedConstraint; + } } } } @@ -14852,10 +14854,10 @@ namespace ts { return isInJavaScriptFile ? anyType : emptyObjectType; } - function getInferredTypes(context: InferenceContext): Type[] { + function getInferredTypes(context: InferenceContext, ignoreConstraints = false): Type[] { const result: Type[] = []; for (let i = 0; i < context.inferences.length; i++) { - result.push(getInferredType(context, i)); + result.push(getInferredType(context, i, ignoreConstraints)); } return result; } @@ -19925,7 +19927,10 @@ namespace ts { inferTypes(context.inferences, spreadType, restType); } - return getInferredTypes(context); + // If we are excluding context sensitive arguments we know there is another round of type inference + // coming, so we omit constraint checking. Otherwise, when a type parameter's constraint is self- + // referential, checking the constraint would cause inferences to be fixed prematurely. + return getInferredTypes(context, !!excludeArgument); } function getArrayifiedType(type: Type) {