Skip to content

Commit bf084f1

Browse files
committed
Merge pull request microsoft#640 from Microsoft/contextualSignatureInstantiation
Fix contextual signature instantiation during type inference
2 parents 163674d + 2b58a23 commit bf084f1

File tree

3 files changed

+24
-20
lines changed

3 files changed

+24
-20
lines changed

src/compiler/checker.ts

+19-15
Original file line numberDiff line numberDiff line change
@@ -4088,19 +4088,6 @@ module ts {
40884088
return getSignatureInstantiation(signature, getInferredTypes(context));
40894089
}
40904090

4091-
// Inferentially type an expression by a contextual parameter type (section 4.12.2 in TypeScript spec)
4092-
function inferentiallyTypeExpession(expr: Expression, contextualType: Type, contextualMapper: TypeMapper): Type {
4093-
var type = checkExpressionWithContextualType(expr, contextualType, contextualMapper);
4094-
var signature = getSingleCallSignature(type);
4095-
if (signature && signature.typeParameters) {
4096-
var contextualSignature = getSingleCallSignature(contextualType);
4097-
if (contextualSignature && !contextualSignature.typeParameters) {
4098-
type = getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
4099-
}
4100-
}
4101-
return type;
4102-
}
4103-
41044091
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument?: boolean[]): Type[] {
41054092
var typeParameters = signature.typeParameters;
41064093
var context = createInferenceContext(typeParameters);
@@ -4109,15 +4096,15 @@ module ts {
41094096
for (var i = 0; i < args.length; i++) {
41104097
if (!excludeArgument || excludeArgument[i] === undefined) {
41114098
var parameterType = getTypeAtPosition(signature, i);
4112-
inferTypes(context, inferentiallyTypeExpession(args[i], parameterType, mapper), parameterType);
4099+
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
41134100
}
41144101
}
41154102
// Next, infer from those context sensitive arguments that are no longer excluded
41164103
if (excludeArgument) {
41174104
for (var i = 0; i < args.length; i++) {
41184105
if (excludeArgument[i] === false) {
41194106
var parameterType = getTypeAtPosition(signature, i);
4120-
inferTypes(context, inferentiallyTypeExpession(args[i], parameterType, mapper), parameterType);
4107+
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
41214108
}
41224109
}
41234110
}
@@ -4852,6 +4839,23 @@ module ts {
48524839
// have the wildcard function type; this form of type check is used during overload resolution to exclude
48534840
// contextually typed function and arrow expressions in the initial phase.
48544841
function checkExpression(node: Expression, contextualMapper?: TypeMapper): Type {
4842+
var type = checkExpressionNode(node, contextualMapper);
4843+
if (contextualMapper && contextualMapper !== identityMapper) {
4844+
var signature = getSingleCallSignature(type);
4845+
if (signature && signature.typeParameters) {
4846+
var contextualType = getContextualType(node);
4847+
if (contextualType) {
4848+
var contextualSignature = getSingleCallSignature(contextualType);
4849+
if (contextualSignature && !contextualSignature.typeParameters) {
4850+
type = getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
4851+
}
4852+
}
4853+
}
4854+
}
4855+
return type;
4856+
}
4857+
4858+
function checkExpressionNode(node: Expression, contextualMapper: TypeMapper): Type {
48554859
switch (node.kind) {
48564860
case SyntaxKind.Identifier:
48574861
return checkIdentifier(<Identifier>node);

tests/baselines/reference/genericCallWithFunctionTypedArguments5.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
// more args not allowed
1111
var r2 = foo({ cb: <T>(x: T, y: T) => '' }); // error
1212
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13-
!!! Argument of type '{ cb: <T>(x: T, y: T) => string; }' is not assignable to parameter of type '{ cb: (t: any) => string; }'.
13+
!!! Argument of type '{ cb: <T>(x: T, y: T) => string; }' is not assignable to parameter of type '{ cb: (t: {}) => string; }'.
1414
!!! Types of property 'cb' are incompatible:
15-
!!! Type '<T>(x: T, y: T) => string' is not assignable to type '(t: any) => string'.
15+
!!! Type '<T>(x: T, y: T) => string' is not assignable to type '(t: {}) => string'.
1616
var r3 = foo({ cb: (x: string, y: number) => '' }); // error
1717
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1818
!!! Argument of type '{ cb: (x: string, y: number) => string; }' is not assignable to parameter of type '{ cb: (t: string) => string; }'.

tests/baselines/reference/inferentialTypingWithFunctionTypeNested.types

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ declare function identity<V>(y: V): V;
2020
>V : V
2121

2222
var s = map("", () => { return { x: identity }; });
23-
>s : any
24-
>map("", () => { return { x: identity }; }) : any
23+
>s : string
24+
>map("", () => { return { x: identity }; }) : string
2525
>map : <T, U>(x: T, f: () => { x: (s: T) => U; }) => U
26-
>() => { return { x: identity }; } : () => { x: <V>(y: V) => V; }
26+
>() => { return { x: identity }; } : () => { x: (y: string) => string; }
2727
>{ x: identity } : { x: <V>(y: V) => V; }
2828
>x : <V>(y: V) => V
2929
>identity : <V>(y: V) => V

0 commit comments

Comments
 (0)