From de3871a4fcc1b3f412883a13ad0d3790b5dac012 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 27 Feb 2018 15:10:43 -0800 Subject: [PATCH] Propagate 'never' and the wildcard type in type inference --- src/compiler/checker.ts | 25 ++++++++++++++++++------- src/compiler/types.ts | 3 +++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d7fbe746927..cf15ca84784 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11496,8 +11496,15 @@ namespace ts { if (!couldContainTypeVariables(target)) { return; } - if (source === wildcardType) { - source = getWildcardInstantiation(target); + if (source === neverType || source === wildcardType) { + // We are inferring from 'never' or the wildcard type. We want to infer this + // type for every type parameter referenced in the target type, so we infer from + // target to itself with a flag we check when recording candidates. + const savePriority = priority; + priority |= source === neverType ? InferencePriority.Never : InferencePriority.Wildcard; + inferFromTypes(target, target); + priority = savePriority; + return; } if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) { // Source and target are types originating in the same generic type alias declaration. @@ -11560,17 +11567,21 @@ namespace ts { const inference = getInferenceInfoForType(target); if (inference) { if (!inference.isFixed) { - if (inference.priority === undefined || priority < inference.priority) { + const p = priority & InferencePriority.Mask; + if (inference.priority === undefined || p < inference.priority) { inference.candidates = undefined; inference.contraCandidates = undefined; - inference.priority = priority; + inference.priority = p; } - if (priority === inference.priority) { + if (p === inference.priority) { + const candidate = priority & InferencePriority.Never ? neverType : + priority & InferencePriority.Wildcard ? wildcardType : + source; if (contravariant) { - inference.contraCandidates = append(inference.contraCandidates, source); + inference.contraCandidates = append(inference.contraCandidates, candidate); } else { - inference.candidates = append(inference.candidates, source); + inference.candidates = append(inference.candidates, candidate); } } if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4f5dc46f4fc..cd5f7dda442 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3915,6 +3915,9 @@ namespace ts { ReturnType = 1 << 2, // Inference made from return type of generic function NoConstraints = 1 << 3, // Don't infer from constraints of instantiable types AlwaysStrict = 1 << 4, // Always use strict rules for contravariant inferences + Wildcard = 1 << 5, // Inferring from wildcard type + Never = 1 << 6, // Inferring from never type + Mask = NakedTypeVariable | MappedType | ReturnType, } /* @internal */