From 8a8b22eacbdf181a54ba6dc615ceadc3fca34391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 28 Jun 2023 17:04:46 +0200 Subject: [PATCH 1/2] Defer processing of nested generic calls that return constructor types --- src/compiler/checker.ts | 10 +++- ...ericNestedCallReturningConstructor.symbols | 59 +++++++++++++++++++ ...enericNestedCallReturningConstructor.types | 53 +++++++++++++++++ ...ceGenericNestedCallReturningConstructor.ts | 22 +++++++ 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols create mode 100644 tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types create mode 100644 tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 92116ccdda172..6600430b47f6c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -33667,7 +33667,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // use the resolvingSignature singleton to indicate that we deferred processing. This result will be // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and // from which we never make inferences). - if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -33680,8 +33680,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunction(signature: Signature) { - return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); + function isGenericFunctionReturningFunctionOrConstructor(signature: Signature) { + if (!signature.typeParameters) { + return false; + } + const returnType = getReturnTypeOfSignature(signature); + return isFunctionType(returnType) || isConstructorType(returnType); } /** diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols new file mode 100644 index 0000000000000..2b7310833cb16 --- /dev/null +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols @@ -0,0 +1,59 @@ +//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// + +=== inferenceGenericNestedCallReturningConstructor.ts === +interface AssignObject { +>AssignObject : Symbol(AssignObject, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 23)) + + new (ctx: TContext): void; +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 1, 7)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 23)) +} + +declare function assign( +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 24)) + + assigner: (ctx: TContext) => void +>assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 34)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 13)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 24)) + +): AssignObject; +>AssignObject : Symbol(AssignObject, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 24)) + +declare function createMachine(config: { +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 26)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 31)) +>config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 41)) + + context: TContext; +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 50)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 31)) + + entry: AssignObject; +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 20)) +>AssignObject : Symbol(AssignObject, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 31)) + +}): void; + +createMachine({ +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 26)) + + context: { count: 0 }, +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 13, 15)) +>count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 12)) + + entry: assign((ctx) => { +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 24)) +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 17)) + + ctx // { count: number } +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 17)) + + }), +}); + diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types new file mode 100644 index 0000000000000..41b2e3253f01a --- /dev/null +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types @@ -0,0 +1,53 @@ +//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// + +=== inferenceGenericNestedCallReturningConstructor.ts === +interface AssignObject { + new (ctx: TContext): void; +>ctx : TContext +} + +declare function assign( +>assign : (assigner: (ctx: TContext) => void) => AssignObject + + assigner: (ctx: TContext) => void +>assigner : (ctx: TContext) => void +>ctx : TContext + +): AssignObject; + +declare function createMachine(config: { +>createMachine : (config: { context: TContext; entry: AssignObject;}) => void +>config : { context: TContext; entry: AssignObject; } + + context: TContext; +>context : TContext + + entry: AssignObject; +>entry : AssignObject + +}): void; + +createMachine({ +>createMachine({ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),}) : void +>createMachine : (config: { context: TContext; entry: AssignObject; }) => void +>{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: AssignObject<{ count: number; }>; } + + context: { count: 0 }, +>context : { count: number; } +>{ count: 0 } : { count: number; } +>count : number +>0 : 0 + + entry: assign((ctx) => { +>entry : AssignObject<{ count: number; }> +>assign((ctx) => { ctx // { count: number } }) : AssignObject<{ count: number; }> +>assign : (assigner: (ctx: TContext) => void) => AssignObject +>(ctx) => { ctx // { count: number } } : (ctx: { count: number; }) => void +>ctx : { count: number; } + + ctx // { count: number } +>ctx : { count: number; } + + }), +}); + diff --git a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts new file mode 100644 index 0000000000000..4ce9564af9220 --- /dev/null +++ b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts @@ -0,0 +1,22 @@ +// @strict: true +// @noEmit: true + +interface AssignObject { + new (ctx: TContext): void; +} + +declare function assign( + assigner: (ctx: TContext) => void +): AssignObject; + +declare function createMachine(config: { + context: TContext; + entry: AssignObject; +}): void; + +createMachine({ + context: { count: 0 }, + entry: assign((ctx) => { + ctx // { count: number } + }), +}); From e0a1e0d115650e8233c121a87e36cab73ba0740a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 28 Jun 2023 17:48:56 +0200 Subject: [PATCH 2/2] make the test case more realistic --- ...ericNestedCallReturningConstructor.symbols | 69 +++++++++++-------- ...enericNestedCallReturningConstructor.types | 34 +++++---- ...ceGenericNestedCallReturningConstructor.ts | 12 +++- 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols index 2b7310833cb16..03e0bcb9f168b 100644 --- a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols @@ -1,58 +1,71 @@ //// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// === inferenceGenericNestedCallReturningConstructor.ts === -interface AssignObject { ->AssignObject : Symbol(AssignObject, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 23)) +interface Action { +>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) new (ctx: TContext): void; >ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 1, 7)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 23)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) +} + +declare class AssignAction { +>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) + + constructor(ctx: TContext); +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 14)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) } declare function assign( ->assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 24)) +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) assigner: (ctx: TContext) => void ->assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 34)) ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 13)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 24)) +>assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 34)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 13)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) -): AssignObject; ->AssignObject : Symbol(AssignObject, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 24)) +): { + new (ctx: TContext): AssignAction; +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 11, 7)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) +>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) +} declare function createMachine(config: { ->createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 26)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 31)) ->config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 41)) +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) +>config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 41)) context: TContext; ->context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 50)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 31)) +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 50)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) - entry: AssignObject; ->entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 20)) ->AssignObject : Symbol(AssignObject, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 31)) + entry: Action; +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 20)) +>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) }): void; createMachine({ ->createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 26)) +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) context: { count: 0 }, ->context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 13, 15)) ->count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 12)) +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 19, 15)) +>count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 12)) entry: assign((ctx) => { ->entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 24)) ->assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 17)) +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 24)) +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) ctx // { count: number } ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 17)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) }), }); diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types index 41b2e3253f01a..ce6d09b4d3281 100644 --- a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types @@ -1,36 +1,46 @@ //// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// === inferenceGenericNestedCallReturningConstructor.ts === -interface AssignObject { +interface Action { new (ctx: TContext): void; >ctx : TContext } +declare class AssignAction { +>AssignAction : AssignAction + + constructor(ctx: TContext); +>ctx : TContext +} + declare function assign( ->assign : (assigner: (ctx: TContext) => void) => AssignObject +>assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction assigner: (ctx: TContext) => void >assigner : (ctx: TContext) => void >ctx : TContext -): AssignObject; +): { + new (ctx: TContext): AssignAction; +>ctx : TContext +} declare function createMachine(config: { ->createMachine : (config: { context: TContext; entry: AssignObject;}) => void ->config : { context: TContext; entry: AssignObject; } +>createMachine : (config: { context: TContext; entry: Action;}) => void +>config : { context: TContext; entry: Action; } context: TContext; >context : TContext - entry: AssignObject; ->entry : AssignObject + entry: Action; +>entry : Action }): void; createMachine({ >createMachine({ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),}) : void ->createMachine : (config: { context: TContext; entry: AssignObject; }) => void ->{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: AssignObject<{ count: number; }>; } +>createMachine : (config: { context: TContext; entry: Action; }) => void +>{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: new (ctx: { count: number; }) => AssignAction<{ count: number; }>; } context: { count: 0 }, >context : { count: number; } @@ -39,9 +49,9 @@ createMachine({ >0 : 0 entry: assign((ctx) => { ->entry : AssignObject<{ count: number; }> ->assign((ctx) => { ctx // { count: number } }) : AssignObject<{ count: number; }> ->assign : (assigner: (ctx: TContext) => void) => AssignObject +>entry : new (ctx: { count: number; }) => AssignAction<{ count: number; }> +>assign((ctx) => { ctx // { count: number } }) : new (ctx: { count: number; }) => AssignAction<{ count: number; }> +>assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction >(ctx) => { ctx // { count: number } } : (ctx: { count: number; }) => void >ctx : { count: number; } diff --git a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts index 4ce9564af9220..8c1ea32096284 100644 --- a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts +++ b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts @@ -1,17 +1,23 @@ // @strict: true // @noEmit: true -interface AssignObject { +interface Action { new (ctx: TContext): void; } +declare class AssignAction { + constructor(ctx: TContext); +} + declare function assign( assigner: (ctx: TContext) => void -): AssignObject; +): { + new (ctx: TContext): AssignAction; +} declare function createMachine(config: { context: TContext; - entry: AssignObject; + entry: Action; }): void; createMachine({