diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e87a92355aff8..9af709de21963 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -38952,7 +38952,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!signature) { return; } - if (isContextSensitive(node)) { + const isNodeContextSensitive = isContextSensitive(node); + if (isNodeContextSensitive) { if (contextualSignature) { const inferenceContext = getInferenceContext(node); let instantiatedContextualSignature: Signature | undefined; @@ -38982,7 +38983,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let contextualReturnType: Type; let returnType: Type; - if (checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { + if (isNodeContextSensitive && checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { const inferenceContext = getInferenceContext(node); const isReturnContextSensitive = !!node.body && (node.body.kind === SyntaxKind.Block ? forEachReturnStatement(node.body as Block, statement => !!statement.expression && isContextSensitive(statement.expression)) : isContextSensitive(node.body)); returnType = getReturnTypeFromBody(node, checkMode | (isReturnContextSensitive ? CheckMode.SkipContextSensitive : 0)); @@ -38994,10 +38995,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { returnType = getReturnTypeFromBody(node, checkMode); } - - if (!signature.resolvedReturnType) { - signature.resolvedReturnType = returnType; - } + signature.resolvedReturnType ??= returnType; } checkSignatureDeclaration(node); } diff --git a/tests/baselines/reference/genericFunctionInference3.symbols b/tests/baselines/reference/genericFunctionInference3.symbols new file mode 100644 index 0000000000000..9107acf987c2d --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference3.symbols @@ -0,0 +1,111 @@ +//// [tests/cases/compiler/genericFunctionInference3.ts] //// + +=== genericFunctionInference3.ts === +const enum SyntaxKind { +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) + + JSDocAllType, +>JSDocAllType : Symbol(SyntaxKind.JSDocAllType, Decl(genericFunctionInference3.ts, 0, 23)) + + JSDocUnknownType, +>JSDocUnknownType : Symbol(SyntaxKind.JSDocUnknownType, Decl(genericFunctionInference3.ts, 1, 15)) +} + +interface Node { +>Node : Symbol(Node, Decl(genericFunctionInference3.ts, 3, 1)) + + readonly kind: SyntaxKind; +>kind : Symbol(Node.kind, Decl(genericFunctionInference3.ts, 5, 16)) +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) +} + +interface TypeNode extends Node { +>TypeNode : Symbol(TypeNode, Decl(genericFunctionInference3.ts, 7, 1)) +>Node : Symbol(Node, Decl(genericFunctionInference3.ts, 3, 1)) + + _typeNodeBrand: any; +>_typeNodeBrand : Symbol(TypeNode._typeNodeBrand, Decl(genericFunctionInference3.ts, 9, 33)) +} + +interface JSDocType extends TypeNode { +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) +>TypeNode : Symbol(TypeNode, Decl(genericFunctionInference3.ts, 7, 1)) + + _jsDocTypeBrand: any; +>_jsDocTypeBrand : Symbol(JSDocType._jsDocTypeBrand, Decl(genericFunctionInference3.ts, 13, 38)) +} + +export interface JSDocAllType extends JSDocType { +>JSDocAllType : Symbol(JSDocAllType, Decl(genericFunctionInference3.ts, 15, 1)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) + + readonly kind: SyntaxKind.JSDocAllType; +>kind : Symbol(JSDocAllType.kind, Decl(genericFunctionInference3.ts, 17, 49)) +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) +>JSDocAllType : Symbol(SyntaxKind.JSDocAllType, Decl(genericFunctionInference3.ts, 0, 23)) +} + +export interface JSDocUnknownType extends JSDocType { +>JSDocUnknownType : Symbol(JSDocUnknownType, Decl(genericFunctionInference3.ts, 19, 1)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) + + readonly kind: SyntaxKind.JSDocUnknownType; +>kind : Symbol(JSDocUnknownType.kind, Decl(genericFunctionInference3.ts, 21, 53)) +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) +>JSDocUnknownType : Symbol(SyntaxKind.JSDocUnknownType, Decl(genericFunctionInference3.ts, 1, 15)) +} + +type Mutable = { -readonly [K in keyof T]: T[K] }; +>Mutable : Symbol(Mutable, Decl(genericFunctionInference3.ts, 23, 1)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 25, 13)) +>K : Symbol(K, Decl(genericFunctionInference3.ts, 25, 46)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 25, 13)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 25, 13)) +>K : Symbol(K, Decl(genericFunctionInference3.ts, 25, 46)) + +declare function createJSDocPrimaryTypeWorker( +>createJSDocPrimaryTypeWorker : Symbol(createJSDocPrimaryTypeWorker, Decl(genericFunctionInference3.ts, 25, 68)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 27, 46)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) + + kind: T["kind"], +>kind : Symbol(kind, Decl(genericFunctionInference3.ts, 27, 67)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 27, 46)) + +): Mutable; +>Mutable : Symbol(Mutable, Decl(genericFunctionInference3.ts, 23, 1)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 27, 46)) + +declare function memoizeOne( +>memoizeOne : Symbol(memoizeOne, Decl(genericFunctionInference3.ts, 29, 14)) +>A : Symbol(A, Decl(genericFunctionInference3.ts, 31, 28)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 31, 76)) + + callback: (arg: A) => T, +>callback : Symbol(callback, Decl(genericFunctionInference3.ts, 31, 80)) +>arg : Symbol(arg, Decl(genericFunctionInference3.ts, 32, 13)) +>A : Symbol(A, Decl(genericFunctionInference3.ts, 31, 28)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 31, 76)) + +): (arg: A) => T; +>arg : Symbol(arg, Decl(genericFunctionInference3.ts, 33, 4)) +>A : Symbol(A, Decl(genericFunctionInference3.ts, 31, 28)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 31, 76)) + +export const getJSDocPrimaryTypeCreateFunction = memoizeOne( +>getJSDocPrimaryTypeCreateFunction : Symbol(getJSDocPrimaryTypeCreateFunction, Decl(genericFunctionInference3.ts, 35, 12)) +>memoizeOne : Symbol(memoizeOne, Decl(genericFunctionInference3.ts, 29, 14)) + + (kind: T["kind"]) => +>T : Symbol(T, Decl(genericFunctionInference3.ts, 36, 3)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) +>kind : Symbol(kind, Decl(genericFunctionInference3.ts, 36, 24)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 36, 3)) + + () => + createJSDocPrimaryTypeWorker(kind), +>createJSDocPrimaryTypeWorker : Symbol(createJSDocPrimaryTypeWorker, Decl(genericFunctionInference3.ts, 25, 68)) +>kind : Symbol(kind, Decl(genericFunctionInference3.ts, 36, 24)) + +); + diff --git a/tests/baselines/reference/genericFunctionInference3.types b/tests/baselines/reference/genericFunctionInference3.types new file mode 100644 index 0000000000000..a20572c980794 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference3.types @@ -0,0 +1,104 @@ +//// [tests/cases/compiler/genericFunctionInference3.ts] //// + +=== genericFunctionInference3.ts === +const enum SyntaxKind { +>SyntaxKind : SyntaxKind +> : ^^^^^^^^^^ + + JSDocAllType, +>JSDocAllType : SyntaxKind.JSDocAllType +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + JSDocUnknownType, +>JSDocUnknownType : SyntaxKind.JSDocUnknownType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +interface Node { + readonly kind: SyntaxKind; +>kind : SyntaxKind +> : ^^^^^^^^^^ +} + +interface TypeNode extends Node { + _typeNodeBrand: any; +>_typeNodeBrand : any +} + +interface JSDocType extends TypeNode { + _jsDocTypeBrand: any; +>_jsDocTypeBrand : any +} + +export interface JSDocAllType extends JSDocType { + readonly kind: SyntaxKind.JSDocAllType; +>kind : SyntaxKind.JSDocAllType +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>SyntaxKind : any +> : ^^^ +} + +export interface JSDocUnknownType extends JSDocType { + readonly kind: SyntaxKind.JSDocUnknownType; +>kind : SyntaxKind.JSDocUnknownType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>SyntaxKind : any +> : ^^^ +} + +type Mutable = { -readonly [K in keyof T]: T[K] }; +>Mutable : Mutable +> : ^^^^^^^^^^ + +declare function createJSDocPrimaryTypeWorker( +>createJSDocPrimaryTypeWorker : (kind: T["kind"]) => Mutable +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + kind: T["kind"], +>kind : T["kind"] +> : ^^^^^^^^^ + +): Mutable; + +declare function memoizeOne( +>memoizeOne : (callback: (arg: A) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + callback: (arg: A) => T, +>callback : (arg: A) => T +> : ^ ^^ ^^^^^ +>arg : A +> : ^ + +): (arg: A) => T; +>arg : A +> : ^ + +export const getJSDocPrimaryTypeCreateFunction = memoizeOne( +>getJSDocPrimaryTypeCreateFunction : (arg: T["kind"]) => () => Mutable +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>memoizeOne( (kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind),) : (arg: T["kind"]) => () => Mutable +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>memoizeOne : (callback: (arg: A) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + (kind: T["kind"]) => +>(kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind) : (kind: T["kind"]) => () => Mutable +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^ +>kind : T["kind"] +> : ^^^^^^^^^ + + () => +>() => createJSDocPrimaryTypeWorker(kind) : () => Mutable +> : ^^^^^^^^^^^^^^^^ + + createJSDocPrimaryTypeWorker(kind), +>createJSDocPrimaryTypeWorker(kind) : Mutable +> : ^^^^^^^^^^ +>createJSDocPrimaryTypeWorker : (kind: T_1["kind"]) => Mutable +> : ^^^^^^^^^^^^^ ^^ ^^ ^^^^^ +>kind : T["kind"] +> : ^^^^^^^^^ + +); + diff --git a/tests/cases/compiler/genericFunctionInference3.ts b/tests/cases/compiler/genericFunctionInference3.ts new file mode 100644 index 0000000000000..79d538f1b28ec --- /dev/null +++ b/tests/cases/compiler/genericFunctionInference3.ts @@ -0,0 +1,43 @@ +// @strict: true +// @noEmit: true + +const enum SyntaxKind { + JSDocAllType, + JSDocUnknownType, +} + +interface Node { + readonly kind: SyntaxKind; +} + +interface TypeNode extends Node { + _typeNodeBrand: any; +} + +interface JSDocType extends TypeNode { + _jsDocTypeBrand: any; +} + +export interface JSDocAllType extends JSDocType { + readonly kind: SyntaxKind.JSDocAllType; +} + +export interface JSDocUnknownType extends JSDocType { + readonly kind: SyntaxKind.JSDocUnknownType; +} + +type Mutable = { -readonly [K in keyof T]: T[K] }; + +declare function createJSDocPrimaryTypeWorker( + kind: T["kind"], +): Mutable; + +declare function memoizeOne( + callback: (arg: A) => T, +): (arg: A) => T; + +export const getJSDocPrimaryTypeCreateFunction = memoizeOne( + (kind: T["kind"]) => + () => + createJSDocPrimaryTypeWorker(kind), +);