Skip to content

Commit b8d5eff

Browse files
committed
Move return type inference to inferTypeArguments function
1 parent 77e2f09 commit b8d5eff

File tree

2 files changed

+24
-26
lines changed

2 files changed

+24
-26
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7924,7 +7924,7 @@ namespace ts {
79247924

79257925
function cloneTypeMapper(mapper: TypeMapper): TypeMapper {
79267926
return mapper && isInferenceContext(mapper) ?
7927-
createInferenceContext(mapper.callNode, mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) :
7927+
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) :
79287928
mapper;
79297929
}
79307930

@@ -10121,11 +10121,10 @@ namespace ts {
1012110121
}
1012210122
}
1012310123

10124-
function createInferenceContext(callNode: CallLikeExpression, signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext {
10124+
function createInferenceContext(signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext {
1012510125
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo);
1012610126
const context = mapper as InferenceContext;
1012710127
context.mappedTypes = signature.typeParameters;
10128-
context.callNode = callNode;
1012910128
context.signature = signature;
1013010129
context.inferences = inferences;
1013110130
context.flags = flags;
@@ -10302,15 +10301,15 @@ namespace ts {
1030210301
// Even if an inference is marked as fixed, we can add candidates from inferences made
1030310302
// from the return type of generic functions (which only happens when no other candidates
1030410303
// are present).
10305-
if (!inference.isFixed || priority & InferencePriority.ReturnType) {
10304+
if (!inference.isFixed) {
1030610305
if (!inference.candidates || priority < inference.priority) {
1030710306
inference.candidates = [source];
1030810307
inference.priority = priority;
1030910308
}
1031010309
else if (priority === inference.priority) {
1031110310
inference.candidates.push(source);
1031210311
}
10313-
if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
10312+
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
1031410313
inference.topLevel = false;
1031510314
}
1031610315
}
@@ -10523,24 +10522,6 @@ namespace ts {
1052310522
let inferredType = inference.inferredType;
1052410523
let inferenceSucceeded: boolean;
1052510524
if (!inferredType) {
10526-
if (!inference.candidates && context.callNode && isExpression(context.callNode)) {
10527-
// We have no inference candidates. Now attempt to get the contextual type for the call
10528-
// expression associated with the context, and if a contextual type is available, infer
10529-
// from that type to the return type of the call expression. For example, given a
10530-
// 'function wrap<T, U>(cb: (x: T) => U): (x: T) => U' and a call expression
10531-
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type
10532-
// of 'f' to the return type of 'wrap'.
10533-
const contextualType = getContextualType(context.callNode);
10534-
if (contextualType) {
10535-
// We clone the contextual mapper to avoid disturbing a resolution in progress for an
10536-
// outer call expression. Effectively we just want a snapshot of whatever has been
10537-
// inferred for any outer call expression so far.
10538-
const mapper = cloneTypeMapper(getContextualMapper(context.callNode));
10539-
const instantiatedType = instantiateType(contextualType, mapper);
10540-
const returnType = getReturnTypeOfSignature(context.signature);
10541-
inferTypes([inference], instantiatedType, returnType, InferencePriority.ReturnType);
10542-
}
10543-
}
1054410525
if (inference.candidates) {
1054510526
// We widen inferred literal types if
1054610527
// all inferences were made to top-level ocurrences of the type parameter, and
@@ -14866,7 +14847,7 @@ namespace ts {
1486614847

1486714848
// Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
1486814849
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature {
14869-
const context = createInferenceContext(/*callNode*/ undefined, signature, InferenceFlags.InferUnionTypes);
14850+
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes);
1487014851
forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
1487114852
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
1487214853
inferTypes(context.inferences, instantiateType(source, contextualMapper), target);
@@ -14899,6 +14880,24 @@ namespace ts {
1489914880
context.failedTypeParameterIndex = undefined;
1490014881
}
1490114882

14883+
// If a contextual type is available, infer from that type to the return type of the call expression. For
14884+
// example, given a 'function wrap<T, U>(cb: (x: T) => U): (x: T) => U' and a call expression
14885+
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
14886+
// return type of 'wrap'.
14887+
if (isExpression(node)) {
14888+
const contextualType = getContextualType(node);
14889+
if (contextualType) {
14890+
// We clone the contextual mapper to avoid disturbing a resolution in progress for an
14891+
// outer call expression. Effectively we just want a snapshot of whatever has been
14892+
// inferred for any outer call expression so far.
14893+
const mapper = cloneTypeMapper(getContextualMapper(node));
14894+
const instantiatedType = instantiateType(contextualType, mapper);
14895+
const returnType = getReturnTypeOfSignature(signature);
14896+
// Inferences made from return types have lower priority than all other inferences.
14897+
inferTypes(context.inferences, instantiatedType, returnType, InferencePriority.ReturnType);
14898+
}
14899+
}
14900+
1490214901
const thisType = getThisTypeOfSignature(signature);
1490314902
if (thisType) {
1490414903
const thisArgumentNode = getThisArgumentOfCall(node);
@@ -15599,7 +15598,7 @@ namespace ts {
1559915598
let candidate: Signature;
1560015599
let typeArgumentsAreValid: boolean;
1560115600
const inferenceContext = originalCandidate.typeParameters
15602-
? createInferenceContext(node, originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0)
15601+
? createInferenceContext(originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0)
1560315602
: undefined;
1560415603

1560515604
while (true) {

src/compiler/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3361,7 +3361,6 @@ namespace ts {
33613361

33623362
/* @internal */
33633363
export interface InferenceContext extends TypeMapper {
3364-
callNode: CallLikeExpression; // Call expression node for which inferences are made
33653364
signature: Signature; // Generic signature for which inferences are made
33663365
inferences: InferenceInfo[]; // Inferences made for each type parameter
33673366
flags: InferenceFlags; // Inference flags

0 commit comments

Comments
 (0)