From 5e551180764bdab714b55633d7a6ab0fd4da92e6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Sep 2018 18:07:51 -0700 Subject: [PATCH] Only make contravariant inferences from pure contravariant positions --- src/compiler/checker.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d7c86a59055..f3201ecf8af 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,3 +1,6 @@ + + + /* @internal */ namespace ts { const ambientModuleSymbolRegex = /^".+"$/; @@ -13460,6 +13463,7 @@ namespace ts { let symbolStack: Symbol[]; let visited: Map; let contravariant = false; + let bivariant = false; let propagationType: Type; let allowComplexConstraintInference = true; inferFromTypes(originalSource, originalTarget); @@ -13546,7 +13550,9 @@ namespace ts { } if (priority === inference.priority) { const candidate = propagationType || source; - if (contravariant) { + // We make contravariant inferences only if we are in a pure contravariant position, + // i.e. only if we have not descended into a bivariant position. + if (contravariant && !bivariant) { inference.contraCandidates = append(inference.contraCandidates, candidate); } else { @@ -13798,7 +13804,12 @@ namespace ts { function inferFromSignature(source: Signature, target: Signature, skipParameters: boolean) { if (!skipParameters) { + const saveBivariant = bivariant; + const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; + // Once we descend into a bivariant signature we remain bivariant for all nested inferences + bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor; forEachMatchingParameterType(source, target, inferFromContravariantTypes); + bivariant = saveBivariant; } const sourceTypePredicate = getTypePredicateOfSignature(source); const targetTypePredicate = getTypePredicateOfSignature(target);