From 35ebbece49320b48df5a0cb048a08a34256718e0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Mar 2019 09:12:24 -0800 Subject: [PATCH] Minor fixes --- src/compiler/checker.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0d9363dc1d8..bce50c821a5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20036,7 +20036,12 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper, compareTypes?: TypeComparer): Signature { const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes); - const sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + const restType = getEffectiveRestType(contextualSignature); + const mapper = contextualMapper && restType && restType.flags & TypeFlags.TypeParameter ? cloneTypeMapper(contextualMapper) : contextualMapper; + const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); @@ -20221,7 +20226,7 @@ namespace ts { // can be specified by users through attributes property. const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); const checkMode = excludeArgument && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; - const attributesType = checkExpressionWithContextualType(node.attributes, paramType, undefined, checkMode); + const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } @@ -20257,7 +20262,7 @@ namespace ts { const paramType = getTypeAtPosition(signature, i); const checkMode = (excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | (excludeArgument ? CheckMode.SkipGenericFunctions : 0); - const argType = checkExpressionWithContextualType(arg, paramType, undefined, checkMode); + const argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). @@ -21874,7 +21879,7 @@ namespace ts { const functionFlags = getFunctionFlags(func); let type: Type; if (func.body.kind !== SyntaxKind.Block) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~CheckMode.SkipGenericFunctions); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -22064,7 +22069,7 @@ namespace ts { forEachReturnStatement(func.body, returnStatement => { const expr = returnStatement.expression; if (expr) { - let type = checkExpressionCached(expr, checkMode); + let type = checkExpressionCached(expr, checkMode && checkMode && checkMode & ~CheckMode.SkipGenericFunctions); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the