Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22556,15 +22556,11 @@ namespace ts {
inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target));
}
else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) {
contravariant = !contravariant;
inferFromTypes((source as IndexType).type, (target as IndexType).type);
contravariant = !contravariant;
inferFromContravariantTypes((source as IndexType).type, (target as IndexType).type);
}
else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) {
const empty = createEmptyObjectTypeFromStringLiteral(source);
contravariant = !contravariant;
inferWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof);
contravariant = !contravariant;
inferFromContravariantTypesWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof);
}
else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) {
inferFromTypes((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType);
Expand All @@ -22577,10 +22573,7 @@ namespace ts {
}
else if (source.flags & TypeFlags.Substitution) {
inferFromTypes((source as SubstitutionType).baseType, target);
const oldPriority = priority;
priority |= InferencePriority.SubstituteSource;
inferFromTypes((source as SubstitutionType).substitute, target); // Make substitute inference at a lower priority
priority = oldPriority;
inferWithPriority((source as SubstitutionType).substitute, target, InferencePriority.SubstituteSource); // Make substitute inference at a lower priority
}
else if (target.flags & TypeFlags.Conditional) {
invokeOnce(source, target, inferToConditionalType);
Expand Down Expand Up @@ -22631,6 +22624,20 @@ namespace ts {
priority = savePriority;
}

function inferFromContravariantTypesWithPriority(source: Type, target: Type, newPriority: InferencePriority) {
const savePriority = priority;
priority |= newPriority;
inferFromContravariantTypes(source, target);
priority = savePriority;
}

function inferToMultipleTypesWithPriority(source: Type, targets: Type[], targetFlags: TypeFlags, newPriority: InferencePriority) {
const savePriority = priority;
priority |= newPriority;
inferToMultipleTypes(source, targets, targetFlags);
priority = savePriority;
}

function invokeOnce(source: Type, target: Type, action: (source: Type, target: Type) => void) {
const key = source.id + "," + target.id;
const status = visited && visited.get(key);
Expand Down Expand Up @@ -22694,10 +22701,14 @@ namespace ts {
}

function inferFromContravariantTypes(source: Type, target: Type) {
contravariant = !contravariant;
inferFromTypes(source, target);
contravariant = !contravariant;
}

function inferFromContravariantTypesIfStrictFunctionTypes(source: Type, target: Type) {
if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) {
contravariant = !contravariant;
inferFromTypes(source, target);
contravariant = !contravariant;
inferFromContravariantTypes(source, target);
}
else {
inferFromTypes(source, target);
Expand Down Expand Up @@ -22860,11 +22871,8 @@ namespace ts {
inferFromTypes(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target));
}
else {
const savePriority = priority;
priority |= contravariant ? InferencePriority.ContravariantConditional : 0;
const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)];
inferToMultipleTypes(source, targetTypes, target.flags);
priority = savePriority;
inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0);
}
}

Expand Down Expand Up @@ -23059,7 +23067,7 @@ namespace ts {
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;
applyToParameterTypes(source, target, inferFromContravariantTypes);
applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes);
bivariant = saveBivariant;
applyToReturnTypes(source, target, inferFromTypes);
}
Expand Down Expand Up @@ -30072,7 +30080,7 @@ 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, inferenceContext?: InferenceContext, compareTypes?: TypeComparer): Signature {
const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes);
const context = createInferenceContext(signature.typeParameters!, signature, inferenceContext?.flags ?? InferenceFlags.None, compareTypes);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, I think this is cruft from my other PR. Will remove and retest.

// We clone the inferenceContext to avoid fixing. For example, when the source signature is <T>(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.
Expand Down