Skip to content

Commit f6d53bd

Browse files
committed
Revert "assign and resolve some contextual parameter types late"
This reverts commit b97406f.
1 parent b97406f commit f6d53bd

7 files changed

Lines changed: 69 additions & 133 deletions

File tree

src/compiler/checker.ts

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21088,7 +21088,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2108821088
}
2108921089

2109021090
function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) {
21091-
if (node.typeParameters || getEffectiveReturnTypeNode(node) || !node.body) {
21091+
if (getEffectiveReturnTypeNode(node) || !node.body) {
2109221092
return false;
2109321093
}
2109421094
if (node.body.kind !== SyntaxKind.Block) {
@@ -26067,8 +26067,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2606726067
});
2606826068
}
2606926069

26070-
function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void, skipUnannotatedParameters = false) {
26071-
const sourceDeclaredCount = source.parameters.length - (signatureHasRestParameter(source) ? 1 : 0);
26070+
function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
2607226071
const sourceCount = getParameterCount(source);
2607326072
const targetCount = getParameterCount(target);
2607426073
const sourceRestType = getEffectiveRestType(source);
@@ -26083,12 +26082,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2608326082
}
2608426083
}
2608526084
for (let i = 0; i < paramCount; i++) {
26086-
if (skipUnannotatedParameters) {
26087-
const decl = i < sourceDeclaredCount ? source.parameters[i] : signatureHasRestParameter(source) ? source.parameters[sourceDeclaredCount] : undefined;
26088-
if (decl?.valueDeclaration && !getEffectiveTypeAnnotationNode(decl.valueDeclaration)) {
26089-
continue
26090-
}
26091-
}
2609226085
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
2609326086
}
2609426087
if (targetRestType) {
@@ -41383,7 +41376,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4138341376
const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter));
4138441377
applyToParameterTypes(instantiatedSignature, contextualSignature, (source, target) => {
4138541378
inferTypes(inferences, source, target, /*priority*/ 0, /*contravariant*/ true);
41386-
}, /*skipUnannotatedParameters*/ true);
41379+
});
4138741380
if (some(inferences, hasInferenceCandidates)) {
4138841381
// We have inference candidates, indicating that one or more type parameters are referenced
4138941382
// in the parameter types of the contextual signature. Now also infer from the return type.
@@ -41396,7 +41389,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4139641389
if (!hasOverlappingInferences(context.inferences, inferences)) {
4139741390
mergeInferences(context.inferences, inferences);
4139841391
context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
41399-
assignContextualParameterTypes(signature, instantiateSignature(contextualSignature, context.mapper));
4140041392
return getOrCreateTypeFromSignature(instantiatedSignature);
4140141393
}
4140241394
}
@@ -41820,13 +41812,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4182041812
// or if its FunctionBody is strict code(11.1.5).
4182141813
checkGrammarModifiers(node);
4182241814

41823-
if (getEffectiveTypeAnnotationNode(node)) {
41824-
// checking annotated parameters early allows the compiler to find circularties early
41825-
checkVariableLikeDeclaration(node);
41826-
} else {
41827-
// defer resolving the type of unannotated parameters so that late contextual parameter types can be assigned before it
41828-
checkNodeDeferred(node);
41829-
}
41815+
checkVariableLikeDeclaration(node);
4183041816
const func = getContainingFunction(node)!;
4183141817
if (hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) {
4183241818
if (compilerOptions.erasableSyntaxOnly) {
@@ -49172,9 +49158,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4917249158
case SyntaxKind.ClassExpression:
4917349159
checkClassExpressionDeferred(node as ClassExpression);
4917449160
break;
49175-
case SyntaxKind.Parameter:
49176-
checkVariableLikeDeclaration(node as ParameterDeclaration);
49177-
break;
4917849161
case SyntaxKind.TypeParameter:
4917949162
checkTypeParameterDeferred(node as TypeParameterDeclaration);
4918049163
break;

src/compiler/utilities.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10814,20 +10814,17 @@ export function getContainingNodeArray(node: Node): NodeArray<Node> | undefined
1081410814

1081510815
/** @internal */
1081610816
export function hasContextSensitiveParameters(node: FunctionLikeDeclaration): boolean {
10817-
// Functions with type parameters are not context sensitive.
10818-
if (!node.typeParameters) {
10819-
// Functions with any parameters that lack type annotations are context sensitive.
10820-
if (some(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) {
10817+
// Functions with any parameters that lack type annotations are context sensitive.
10818+
if (some(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) {
10819+
return true;
10820+
}
10821+
if (node.kind !== SyntaxKind.ArrowFunction) {
10822+
// If the first parameter is not an explicit 'this' parameter, then the function has
10823+
// an implicit 'this' parameter which is subject to contextual typing.
10824+
const parameter = firstOrUndefined(node.parameters);
10825+
if (!(parameter && parameterIsThisKeyword(parameter))) {
1082110826
return true;
1082210827
}
10823-
if (node.kind !== SyntaxKind.ArrowFunction) {
10824-
// If the first parameter is not an explicit 'this' parameter, then the function has
10825-
// an implicit 'this' parameter which is subject to contextual typing.
10826-
const parameter = firstOrUndefined(node.parameters);
10827-
if (!(parameter && parameterIsThisKeyword(parameter))) {
10828-
return true;
10829-
}
10830-
}
1083110828
}
1083210829
return false;
1083310830
}

tests/baselines/reference/contextualTypingGenericFunction2.errors.txt

Lines changed: 0 additions & 62 deletions
This file was deleted.

tests/baselines/reference/contextualTypingGenericFunction2.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,28 @@ export const ok7 = fnGen1({ message: "foo" }, function* <N>(n: N) {
6262

6363
//// [contextualTypingGenericFunction2.d.ts]
6464
export declare const ok1: (n: number) => void;
65-
export declare const ok2: <N>(n: N) => void;
65+
export declare const ok2: (n: any) => void;
6666
export declare const ok3: <N>(n: N) => void;
6767
export declare const ok4: <N>(n: N) => number;
68-
export declare const ok5: <T>(params: T) => number;
68+
export declare const ok5: (params: T) => number;
6969
export declare const ok6: (n: number) => void;
70-
export declare const ok7: <N>(n: N) => void;
70+
export declare const ok7: (n: any) => void;
71+
72+
73+
//// [DtsFileErrors]
74+
75+
76+
contextualTypingGenericFunction2.d.ts(5,36): error TS2304: Cannot find name 'T'.
77+
78+
79+
==== contextualTypingGenericFunction2.d.ts (1 errors) ====
80+
export declare const ok1: (n: number) => void;
81+
export declare const ok2: (n: any) => void;
82+
export declare const ok3: <N>(n: N) => void;
83+
export declare const ok4: <N>(n: N) => number;
84+
export declare const ok5: (params: T) => number;
85+
~
86+
!!! error TS2304: Cannot find name 'T'.
87+
export declare const ok6: (n: number) => void;
88+
export declare const ok7: (n: any) => void;
89+

tests/baselines/reference/contextualTypingGenericFunction2.types

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ export const ok1 = fn1({ message: "foo" }, function (n: number) {
5656
});
5757

5858
export const ok2 = fn1({ message: "foo" }, function <N>(n: N) {
59-
>ok2 : <N>(n: N) => void
60-
> : ^ ^^^^^^^^^^^^^^^
61-
>fn1({ message: "foo" }, function <N>(n: N) { this.message;}) : <N>(n: N) => void
62-
> : ^ ^^^^^^^^^^^^^^^
59+
>ok2 : (n: any) => void
60+
> : ^^^^^^^^^^^^^^^^
61+
>fn1({ message: "foo" }, function <N>(n: N) { this.message;}) : (n: any) => void
62+
> : ^^^^^^^^^^^^^^^^
6363
>fn1 : <T, Args extends Array<any>, Ret>(self: T, body: (this: T, ...args: Args) => Ret) => (...args: Args) => Ret
6464
> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^
6565
>{ message: "foo" } : { message: string; }
@@ -178,14 +178,14 @@ declare function fn4<T, P>(config: {
178178
> : ^
179179

180180
export const ok5 = fn4({
181-
>ok5 : <T>(params: T) => number
182-
> : ^ ^^ ^^^^^^^^
183-
>fn4({ context: 1, callback: <T,>(params: T) => { return (a, b) => a + 1; },}) : <T>(params: T) => number
184-
> : ^ ^^ ^^^^^^^^
181+
>ok5 : (params: T) => number
182+
> : ^ ^^^^^^^^
183+
>fn4({ context: 1, callback: <T,>(params: T) => { return (a, b) => a + 1; },}) : (params: T) => number
184+
> : ^ ^^^^^^^^
185185
>fn4 : <T, P>(config: { context: T; callback: (params: P) => (context: T, params: P) => number; }) => (params: P) => number
186186
> : ^ ^^ ^^ ^^ ^^^^^
187-
>{ context: 1, callback: <T,>(params: T) => { return (a, b) => a + 1; },} : { context: number; callback: <T>(params: T) => (a: unknown, b: unknown) => any; }
188-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
187+
>{ context: 1, callback: <T,>(params: T) => { return (a, b) => a + 1; },} : { context: number; callback: <T>(params: T) => (a: number, b: T) => number; }
188+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
189189

190190
context: 1,
191191
>context : number
@@ -194,24 +194,24 @@ export const ok5 = fn4({
194194
> : ^
195195

196196
callback: <T,>(params: T) => {
197-
>callback : <T>(params: T) => (a: unknown, b: unknown) => any
198-
> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
199-
><T,>(params: T) => { return (a, b) => a + 1; } : <T>(params: T) => (a: unknown, b: unknown) => any
200-
> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
197+
>callback : <T>(params: T) => (a: number, b: T) => number
198+
> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^
199+
><T,>(params: T) => { return (a, b) => a + 1; } : <T>(params: T) => (a: number, b: T) => number
200+
> : ^ ^^ ^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^
201201
>params : T
202202
> : ^
203203

204204
return (a, b) => a + 1;
205-
>(a, b) => a + 1 : (a: unknown, b: unknown) => any
206-
> : ^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
207-
>a : unknown
208-
> : ^^^^^^^
209-
>b : unknown
210-
> : ^^^^^^^
211-
>a + 1 : any
212-
> : ^^^
213-
>a : unknown
214-
> : ^^^^^^^
205+
>(a, b) => a + 1 : (a: number, b: T) => number
206+
> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^
207+
>a : number
208+
> : ^^^^^^
209+
>b : T
210+
> : ^
211+
>a + 1 : number
212+
> : ^^^^^^
213+
>a : number
214+
> : ^^^^^^
215215
>1 : 1
216216
> : ^
217217

@@ -267,10 +267,10 @@ export const ok6 = fnGen1({ message: "foo" }, function* (n: number) {
267267
});
268268

269269
export const ok7 = fnGen1({ message: "foo" }, function* <N>(n: N) {
270-
>ok7 : <N>(n: N) => void
271-
> : ^ ^^^^^^^^^^^^^^^
272-
>fnGen1({ message: "foo" }, function* <N>(n: N) { this.message;}) : <N>(n: N) => void
273-
> : ^ ^^^^^^^^^^^^^^^
270+
>ok7 : (n: any) => void
271+
> : ^^^^^^^^^^^^^^^^
272+
>fnGen1({ message: "foo" }, function* <N>(n: N) { this.message;}) : (n: any) => void
273+
> : ^^^^^^^^^^^^^^^^
274274
>fnGen1 : <T, Args extends Array<any>, Ret>(self: T, body: (this: T, ...args: Args) => Generator<any, Ret, never>) => (...args: Args) => Ret
275275
> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^
276276
>{ message: "foo" } : { message: string; }

tests/baselines/reference/literalTypes2.types

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,9 @@ function f3() {
375375
> : ^^^^^
376376

377377
const c3 = cond ? E.A : cond ? true : 123;
378-
>c3 : true | 123 | E.A
378+
>c3 : true | E.A | 123
379379
> : ^^^^^^^^^^^^^^^^
380-
>cond ? E.A : cond ? true : 123 : true | 123 | E.A
380+
>cond ? E.A : cond ? true : 123 : true | E.A | 123
381381
> : ^^^^^^^^^^^^^^^^
382382
>cond : boolean
383383
> : ^^^^^^^
@@ -473,7 +473,7 @@ function f3() {
473473
let x3 = c3;
474474
>x3 : number | boolean
475475
> : ^^^^^^^^^^^^^^^^
476-
>c3 : true | 123 | E.A
476+
>c3 : true | E.A | 123
477477
> : ^^^^^^^^^^^^^^^^
478478

479479
let x4 = c4;
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/// <reference path='fourslash.ts'/>
22

3-
// should not contextually type the RHS because it introduces type parameters
43
////var obj: { f<T>(x: T): T } = { f: <S>(/*1*/x) => x };
54
////var obj2: <T>(x: T) => T = <S>(/*2*/x) => x;
65
////
@@ -11,7 +10,7 @@
1110
////c.obj = <S>(/*3*/x) => x;
1211

1312
verify.quickInfos({
14-
1: "(parameter) x: any",
15-
2: "(parameter) x: any",
16-
3: "(parameter) x: any"
13+
1: "(parameter) x: T",
14+
2: "(parameter) x: T",
15+
3: "(parameter) x: T"
1716
});

0 commit comments

Comments
 (0)