From 215335b64ab668333dadb95426e05461433b70b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 2 Sep 2025 15:54:50 +0200 Subject: [PATCH 1/3] Defer checking call and new expressions with context sensitive arguments --- src/compiler/checker.ts | 10 +- .../contextSensitiveCallNewArguments1.symbols | 229 +++++++++++ .../contextSensitiveCallNewArguments1.types | 381 ++++++++++++++++++ ...textuallyTypeAsyncFunctionReturnType.types | 4 +- .../contextSensitiveCallNewArguments1.ts | 86 ++++ 5 files changed, 707 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/contextSensitiveCallNewArguments1.symbols create mode 100644 tests/baselines/reference/contextSensitiveCallNewArguments1.types create mode 100644 tests/cases/compiler/contextSensitiveCallNewArguments1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 66742c94f057e..e67a4a9fe41cf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21141,6 +21141,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const { expression } = node as JsxExpression; return !!expression && isContextSensitive(expression); } + case SyntaxKind.NewExpression: + case SyntaxKind.CallExpression: + return some((node as NewExpression | CallExpression).arguments, isContextSensitive); } return false; @@ -36999,7 +37002,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 (!node.typeArguments && (checkMode & CheckMode.SkipGenericFunctions && callSignatures.some(isGenericFunctionReturningFunction) || checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node))) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -37054,6 +37057,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveUntypedCall(node); } + if (!node.typeArguments && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) { + skippedGenericFunction(node, checkMode); + return resolvingSignature; + } + // Technically, this signatures list may be incomplete. We are taking the apparent type, // but we are not including construct signatures that may have been added to the Object or // Function interface, since they have none by default. This is a bit of a leap of faith diff --git a/tests/baselines/reference/contextSensitiveCallNewArguments1.symbols b/tests/baselines/reference/contextSensitiveCallNewArguments1.symbols new file mode 100644 index 0000000000000..4afa7ac54349e --- /dev/null +++ b/tests/baselines/reference/contextSensitiveCallNewArguments1.symbols @@ -0,0 +1,229 @@ +//// [tests/cases/compiler/contextSensitiveCallNewArguments1.ts] //// + +=== contextSensitiveCallNewArguments1.ts === +// https://github.com/microsoft/TypeScript/issues/62380 + +class Foo { +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>T : Symbol(T, Decl(contextSensitiveCallNewArguments1.ts, 2, 10)) + + constructor(public inner: T) {} +>inner : Symbol(Foo.inner, Decl(contextSensitiveCallNewArguments1.ts, 3, 14)) +>T : Symbol(T, Decl(contextSensitiveCallNewArguments1.ts, 2, 10)) +} + +class BarClass { +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>T : Symbol(T, Decl(contextSensitiveCallNewArguments1.ts, 6, 15)) + + constructor(public accessor: (state: T) => boolean) {} +>accessor : Symbol(BarClass.accessor, Decl(contextSensitiveCallNewArguments1.ts, 7, 14)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 7, 32)) +>T : Symbol(T, Decl(contextSensitiveCallNewArguments1.ts, 6, 15)) +} + +{ + class Container { +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 10, 1)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 11, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 11, 20)) + + constructor( + public ctx: C, +>ctx : Symbol(Container.ctx, Decl(contextSensitiveCallNewArguments1.ts, 12, 16)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 11, 18)) + + public fooFactory: (ctx: C) => F, +>fooFactory : Symbol(Container.fooFactory, Decl(contextSensitiveCallNewArguments1.ts, 13, 20)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 14, 26)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 11, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 11, 20)) + + public bars: BarClass[], +>bars : Symbol(Container.bars, Decl(contextSensitiveCallNewArguments1.ts, 14, 39)) +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 11, 20)) + + ) {} + } + + const container = new Container(42, (ctx) => new Foo({ answer: ctx }), [ +>container : Symbol(container, Decl(contextSensitiveCallNewArguments1.ts, 19, 7)) +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 10, 1)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 19, 39)) +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>answer : Symbol(answer, Decl(contextSensitiveCallNewArguments1.ts, 19, 56)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 19, 39)) + + new BarClass((state) => true), +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 20, 18)) + + ]); +} + +{ + class Container { +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 24, 1)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 25, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 25, 20)) + + constructor( + public ctx: C, +>ctx : Symbol(Container.ctx, Decl(contextSensitiveCallNewArguments1.ts, 26, 16)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 25, 18)) + + public fooFactory: (ctx: C) => F, +>fooFactory : Symbol(Container.fooFactory, Decl(contextSensitiveCallNewArguments1.ts, 27, 20)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 28, 26)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 25, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 25, 20)) + + public bar: BarClass, +>bar : Symbol(Container.bar, Decl(contextSensitiveCallNewArguments1.ts, 28, 39)) +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 25, 20)) + + ) {} + } + + const containerWithoutAnnotation = new Container( +>containerWithoutAnnotation : Symbol(containerWithoutAnnotation, Decl(contextSensitiveCallNewArguments1.ts, 33, 7)) +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 24, 1)) + + 42, + (ctx) => new Foo({ answer: ctx }), +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 35, 5)) +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>answer : Symbol(answer, Decl(contextSensitiveCallNewArguments1.ts, 35, 22)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 35, 5)) + + new BarClass((state) => true), +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 36, 18)) + + ); + + const containerWithAnnotation = new Container( +>containerWithAnnotation : Symbol(containerWithAnnotation, Decl(contextSensitiveCallNewArguments1.ts, 39, 7)) +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 24, 1)) + + 42, + (ctx: number) => new Foo({ answer: ctx }), +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 41, 5)) +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>answer : Symbol(answer, Decl(contextSensitiveCallNewArguments1.ts, 41, 30)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 41, 5)) + + new BarClass((state) => true), +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 42, 18)) + + ); +} + +{ + class Container { +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 46, 1)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 47, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 47, 20)) + + constructor( + public ctx: C, +>ctx : Symbol(Container.ctx, Decl(contextSensitiveCallNewArguments1.ts, 48, 16)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 47, 18)) + + public fooFactory: (ctx: C) => F, +>fooFactory : Symbol(Container.fooFactory, Decl(contextSensitiveCallNewArguments1.ts, 49, 20)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 50, 26)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 47, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 47, 20)) + + public barFactory: () => BarClass, +>barFactory : Symbol(Container.barFactory, Decl(contextSensitiveCallNewArguments1.ts, 50, 39)) +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 47, 20)) + + ) {} + } + + const container = new Container( +>container : Symbol(container, Decl(contextSensitiveCallNewArguments1.ts, 55, 7)) +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 46, 1)) + + 42, + (ctx) => new Foo({ answer: ctx }), +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 57, 5)) +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>answer : Symbol(answer, Decl(contextSensitiveCallNewArguments1.ts, 57, 22)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 57, 5)) + + () => new BarClass((state) => true), +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 58, 24)) + + ); +} + +{ + class Container { +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 62, 1)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 63, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 63, 20)) + + constructor( + public ctx: C, +>ctx : Symbol(Container.ctx, Decl(contextSensitiveCallNewArguments1.ts, 64, 16)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 63, 18)) + + public fooFactory: (ctx: C) => F, +>fooFactory : Symbol(Container.fooFactory, Decl(contextSensitiveCallNewArguments1.ts, 65, 20)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 66, 26)) +>C : Symbol(C, Decl(contextSensitiveCallNewArguments1.ts, 63, 18)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 63, 20)) + + public barFactory: (dummy: never) => BarClass, +>barFactory : Symbol(Container.barFactory, Decl(contextSensitiveCallNewArguments1.ts, 66, 39)) +>dummy : Symbol(dummy, Decl(contextSensitiveCallNewArguments1.ts, 67, 26)) +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>F : Symbol(F, Decl(contextSensitiveCallNewArguments1.ts, 63, 20)) + + ) {} + } + + const containerWithDummy = new Container( +>containerWithDummy : Symbol(containerWithDummy, Decl(contextSensitiveCallNewArguments1.ts, 71, 7)) +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 62, 1)) + + 42, + (ctx) => new Foo({ answer: ctx }), +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 73, 5)) +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>answer : Symbol(answer, Decl(contextSensitiveCallNewArguments1.ts, 73, 22)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 73, 5)) + + (dummy) => new BarClass((state) => true), +>dummy : Symbol(dummy, Decl(contextSensitiveCallNewArguments1.ts, 74, 5)) +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 74, 29)) + + ); + + const containerWithWrongArity = new Container( +>containerWithWrongArity : Symbol(containerWithWrongArity, Decl(contextSensitiveCallNewArguments1.ts, 77, 7)) +>Container : Symbol(Container, Decl(contextSensitiveCallNewArguments1.ts, 62, 1)) + + 42, + (ctx) => new Foo({ answer: ctx }), +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 79, 5)) +>Foo : Symbol(Foo, Decl(contextSensitiveCallNewArguments1.ts, 0, 0)) +>answer : Symbol(answer, Decl(contextSensitiveCallNewArguments1.ts, 79, 22)) +>ctx : Symbol(ctx, Decl(contextSensitiveCallNewArguments1.ts, 79, 5)) + + () => new BarClass((state) => true), +>BarClass : Symbol(BarClass, Decl(contextSensitiveCallNewArguments1.ts, 4, 1)) +>state : Symbol(state, Decl(contextSensitiveCallNewArguments1.ts, 80, 24)) + + ); +} + diff --git a/tests/baselines/reference/contextSensitiveCallNewArguments1.types b/tests/baselines/reference/contextSensitiveCallNewArguments1.types new file mode 100644 index 0000000000000..ee7844fb75cc2 --- /dev/null +++ b/tests/baselines/reference/contextSensitiveCallNewArguments1.types @@ -0,0 +1,381 @@ +//// [tests/cases/compiler/contextSensitiveCallNewArguments1.ts] //// + +=== contextSensitiveCallNewArguments1.ts === +// https://github.com/microsoft/TypeScript/issues/62380 + +class Foo { +>Foo : Foo +> : ^^^^^^ + + constructor(public inner: T) {} +>inner : T +> : ^ +} + +class BarClass { +>BarClass : BarClass +> : ^^^^^^^^^^^ + + constructor(public accessor: (state: T) => boolean) {} +>accessor : (state: T) => boolean +> : ^ ^^ ^^^^^ +>state : T +> : ^ +} + +{ + class Container { +>Container : Container +> : ^^^^^^^^^^^^^^^ + + constructor( + public ctx: C, +>ctx : C +> : ^ + + public fooFactory: (ctx: C) => F, +>fooFactory : (ctx: C) => F +> : ^ ^^ ^^^^^ +>ctx : C +> : ^ + + public bars: BarClass[], +>bars : BarClass[] +> : ^^^^^^^^^^^^^ + + ) {} + } + + const container = new Container(42, (ctx) => new Foo({ answer: ctx }), [ +>container : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Container(42, (ctx) => new Foo({ answer: ctx }), [ new BarClass((state) => true), ]) : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Container : typeof Container +> : ^^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ +>(ctx) => new Foo({ answer: ctx }) : (ctx: number) => Foo<{ answer: number; }> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ctx : number +> : ^^^^^^ +>new Foo({ answer: ctx }) : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>{ answer: ctx } : { answer: number; } +> : ^^^^^^^^^^^^^^^^^^^ +>answer : number +> : ^^^^^^ +>ctx : number +> : ^^^^^^ +>[ new BarClass((state) => true), ] : BarClass>[] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + new BarClass((state) => true), +>new BarClass((state) => true) : BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>BarClass : typeof BarClass +> : ^^^^^^^^^^^^^^^ +>(state) => true : (state: Foo<{ answer: number; }>) => boolean +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>state : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ + + ]); +} + +{ + class Container { +>Container : Container +> : ^^^^^^^^^^^^^^^ + + constructor( + public ctx: C, +>ctx : C +> : ^ + + public fooFactory: (ctx: C) => F, +>fooFactory : (ctx: C) => F +> : ^ ^^ ^^^^^ +>ctx : C +> : ^ + + public bar: BarClass, +>bar : BarClass +> : ^^^^^^^^^^^ + + ) {} + } + + const containerWithoutAnnotation = new Container( +>containerWithoutAnnotation : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Container( 42, (ctx) => new Foo({ answer: ctx }), new BarClass((state) => true), ) : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Container : typeof Container +> : ^^^^^^^^^^^^^^^^ + + 42, +>42 : 42 +> : ^^ + + (ctx) => new Foo({ answer: ctx }), +>(ctx) => new Foo({ answer: ctx }) : (ctx: number) => Foo<{ answer: number; }> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ctx : number +> : ^^^^^^ +>new Foo({ answer: ctx }) : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>{ answer: ctx } : { answer: number; } +> : ^^^^^^^^^^^^^^^^^^^ +>answer : number +> : ^^^^^^ +>ctx : number +> : ^^^^^^ + + new BarClass((state) => true), +>new BarClass((state) => true) : BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>BarClass : typeof BarClass +> : ^^^^^^^^^^^^^^^ +>(state) => true : (state: Foo<{ answer: number; }>) => boolean +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>state : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ + + ); + + const containerWithAnnotation = new Container( +>containerWithAnnotation : Container<42, Foo<{ answer: number; }>> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Container( 42, (ctx: number) => new Foo({ answer: ctx }), new BarClass((state) => true), ) : Container<42, Foo<{ answer: number; }>> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Container : typeof Container +> : ^^^^^^^^^^^^^^^^ + + 42, +>42 : 42 +> : ^^ + + (ctx: number) => new Foo({ answer: ctx }), +>(ctx: number) => new Foo({ answer: ctx }) : (ctx: number) => Foo<{ answer: number; }> +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ctx : number +> : ^^^^^^ +>new Foo({ answer: ctx }) : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>{ answer: ctx } : { answer: number; } +> : ^^^^^^^^^^^^^^^^^^^ +>answer : number +> : ^^^^^^ +>ctx : number +> : ^^^^^^ + + new BarClass((state) => true), +>new BarClass((state) => true) : BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>BarClass : typeof BarClass +> : ^^^^^^^^^^^^^^^ +>(state) => true : (state: Foo<{ answer: number; }>) => boolean +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>state : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ + + ); +} + +{ + class Container { +>Container : Container +> : ^^^^^^^^^^^^^^^ + + constructor( + public ctx: C, +>ctx : C +> : ^ + + public fooFactory: (ctx: C) => F, +>fooFactory : (ctx: C) => F +> : ^ ^^ ^^^^^ +>ctx : C +> : ^ + + public barFactory: () => BarClass, +>barFactory : () => BarClass +> : ^^^^^^ + + ) {} + } + + const container = new Container( +>container : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Container( 42, (ctx) => new Foo({ answer: ctx }), () => new BarClass((state) => true), ) : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Container : typeof Container +> : ^^^^^^^^^^^^^^^^ + + 42, +>42 : 42 +> : ^^ + + (ctx) => new Foo({ answer: ctx }), +>(ctx) => new Foo({ answer: ctx }) : (ctx: number) => Foo<{ answer: number; }> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ctx : number +> : ^^^^^^ +>new Foo({ answer: ctx }) : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>{ answer: ctx } : { answer: number; } +> : ^^^^^^^^^^^^^^^^^^^ +>answer : number +> : ^^^^^^ +>ctx : number +> : ^^^^^^ + + () => new BarClass((state) => true), +>() => new BarClass((state) => true) : () => BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new BarClass((state) => true) : BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>BarClass : typeof BarClass +> : ^^^^^^^^^^^^^^^ +>(state) => true : (state: Foo<{ answer: number; }>) => boolean +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>state : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ + + ); +} + +{ + class Container { +>Container : Container +> : ^^^^^^^^^^^^^^^ + + constructor( + public ctx: C, +>ctx : C +> : ^ + + public fooFactory: (ctx: C) => F, +>fooFactory : (ctx: C) => F +> : ^ ^^ ^^^^^ +>ctx : C +> : ^ + + public barFactory: (dummy: never) => BarClass, +>barFactory : (dummy: never) => BarClass +> : ^ ^^ ^^^^^ +>dummy : never +> : ^^^^^ + + ) {} + } + + const containerWithDummy = new Container( +>containerWithDummy : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Container( 42, (ctx) => new Foo({ answer: ctx }), (dummy) => new BarClass((state) => true), ) : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Container : typeof Container +> : ^^^^^^^^^^^^^^^^ + + 42, +>42 : 42 +> : ^^ + + (ctx) => new Foo({ answer: ctx }), +>(ctx) => new Foo({ answer: ctx }) : (ctx: number) => Foo<{ answer: number; }> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ctx : number +> : ^^^^^^ +>new Foo({ answer: ctx }) : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>{ answer: ctx } : { answer: number; } +> : ^^^^^^^^^^^^^^^^^^^ +>answer : number +> : ^^^^^^ +>ctx : number +> : ^^^^^^ + + (dummy) => new BarClass((state) => true), +>(dummy) => new BarClass((state) => true) : (dummy: never) => BarClass> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>dummy : never +> : ^^^^^ +>new BarClass((state) => true) : BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>BarClass : typeof BarClass +> : ^^^^^^^^^^^^^^^ +>(state) => true : (state: Foo<{ answer: number; }>) => boolean +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>state : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ + + ); + + const containerWithWrongArity = new Container( +>containerWithWrongArity : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Container( 42, (ctx) => new Foo({ answer: ctx }), () => new BarClass((state) => true), ) : Container> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Container : typeof Container +> : ^^^^^^^^^^^^^^^^ + + 42, +>42 : 42 +> : ^^ + + (ctx) => new Foo({ answer: ctx }), +>(ctx) => new Foo({ answer: ctx }) : (ctx: number) => Foo<{ answer: number; }> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ctx : number +> : ^^^^^^ +>new Foo({ answer: ctx }) : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ +>{ answer: ctx } : { answer: number; } +> : ^^^^^^^^^^^^^^^^^^^ +>answer : number +> : ^^^^^^ +>ctx : number +> : ^^^^^^ + + () => new BarClass((state) => true), +>() => new BarClass((state) => true) : () => BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new BarClass((state) => true) : BarClass> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>BarClass : typeof BarClass +> : ^^^^^^^^^^^^^^^ +>(state) => true : (state: Foo<{ answer: number; }>) => boolean +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>state : Foo<{ answer: number; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ + + ); +} + diff --git a/tests/baselines/reference/contextuallyTypeAsyncFunctionReturnType.types b/tests/baselines/reference/contextuallyTypeAsyncFunctionReturnType.types index 5d8df0c417280..7dc038509cf27 100644 --- a/tests/baselines/reference/contextuallyTypeAsyncFunctionReturnType.types +++ b/tests/baselines/reference/contextuallyTypeAsyncFunctionReturnType.types @@ -190,8 +190,8 @@ test("windows-process-tree", async () => { > : ^^^^^^^^^^^^ >"windows-process-tree" : "windows-process-tree" > : ^^^^^^^^^^^^^^^^^^^^^^ ->async () => { return new Promise((resolve, reject) => { getProcessTree(123, (tree) => { if (tree) { resolve(); } else { reject(new Error("windows-process-tree")); } }); });} : () => Promise -> : ^^^^^^^^^^^^^^^^^^^ +>async () => { return new Promise((resolve, reject) => { getProcessTree(123, (tree) => { if (tree) { resolve(); } else { reject(new Error("windows-process-tree")); } }); });} : (this: Context) => Promise +> : ^ ^^ ^^^^^^^^^^^^^^^^^^ return new Promise((resolve, reject) => { >new Promise((resolve, reject) => { getProcessTree(123, (tree) => { if (tree) { resolve(); } else { reject(new Error("windows-process-tree")); } }); }) : Promise diff --git a/tests/cases/compiler/contextSensitiveCallNewArguments1.ts b/tests/cases/compiler/contextSensitiveCallNewArguments1.ts new file mode 100644 index 0000000000000..439c3a9fd3c0e --- /dev/null +++ b/tests/cases/compiler/contextSensitiveCallNewArguments1.ts @@ -0,0 +1,86 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/62380 + +class Foo { + constructor(public inner: T) {} +} + +class BarClass { + constructor(public accessor: (state: T) => boolean) {} +} + +{ + class Container { + constructor( + public ctx: C, + public fooFactory: (ctx: C) => F, + public bars: BarClass[], + ) {} + } + + const container = new Container(42, (ctx) => new Foo({ answer: ctx }), [ + new BarClass((state) => true), + ]); +} + +{ + class Container { + constructor( + public ctx: C, + public fooFactory: (ctx: C) => F, + public bar: BarClass, + ) {} + } + + const containerWithoutAnnotation = new Container( + 42, + (ctx) => new Foo({ answer: ctx }), + new BarClass((state) => true), + ); + + const containerWithAnnotation = new Container( + 42, + (ctx: number) => new Foo({ answer: ctx }), + new BarClass((state) => true), + ); +} + +{ + class Container { + constructor( + public ctx: C, + public fooFactory: (ctx: C) => F, + public barFactory: () => BarClass, + ) {} + } + + const container = new Container( + 42, + (ctx) => new Foo({ answer: ctx }), + () => new BarClass((state) => true), + ); +} + +{ + class Container { + constructor( + public ctx: C, + public fooFactory: (ctx: C) => F, + public barFactory: (dummy: never) => BarClass, + ) {} + } + + const containerWithDummy = new Container( + 42, + (ctx) => new Foo({ answer: ctx }), + (dummy) => new BarClass((state) => true), + ); + + const containerWithWrongArity = new Container( + 42, + (ctx) => new Foo({ answer: ctx }), + () => new BarClass((state) => true), + ); +} From 02a447d1fcd4c983db12ebca44b2d54f7de9b29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 3 Sep 2025 09:53:34 +0200 Subject: [PATCH 2/3] only defer in `CheckMode.Inferential` --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e67a4a9fe41cf..52efb73590b05 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -37002,7 +37002,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 (!node.typeArguments && (checkMode & CheckMode.SkipGenericFunctions && callSignatures.some(isGenericFunctionReturningFunction) || checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node))) { + if (!node.typeArguments && (checkMode & CheckMode.SkipGenericFunctions && callSignatures.some(isGenericFunctionReturningFunction) || ((checkMode & (CheckMode.Inferential | CheckMode.SkipContextSensitive)) === (CheckMode.Inferential | CheckMode.SkipContextSensitive)) && isContextSensitive(node))) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -37057,7 +37057,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveUntypedCall(node); } - if (!node.typeArguments && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) { + if (!node.typeArguments && ((checkMode & (CheckMode.Inferential | CheckMode.SkipContextSensitive)) === (CheckMode.Inferential | CheckMode.SkipContextSensitive)) && isContextSensitive(node)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } From 48acd8b8fe59c38011062fb8280c45f616e2dd3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 3 Sep 2025 11:07:11 +0200 Subject: [PATCH 3/3] try with `CheckMode.Contextual` --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 52efb73590b05..090947692b727 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -37002,7 +37002,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 (!node.typeArguments && (checkMode & CheckMode.SkipGenericFunctions && callSignatures.some(isGenericFunctionReturningFunction) || ((checkMode & (CheckMode.Inferential | CheckMode.SkipContextSensitive)) === (CheckMode.Inferential | CheckMode.SkipContextSensitive)) && isContextSensitive(node))) { + if (!node.typeArguments && (checkMode & CheckMode.SkipGenericFunctions && callSignatures.some(isGenericFunctionReturningFunction) || ((checkMode & (CheckMode.Contextual | CheckMode.SkipContextSensitive)) === (CheckMode.Contextual | CheckMode.SkipContextSensitive)) && isContextSensitive(node))) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -37057,7 +37057,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveUntypedCall(node); } - if (!node.typeArguments && ((checkMode & (CheckMode.Inferential | CheckMode.SkipContextSensitive)) === (CheckMode.Inferential | CheckMode.SkipContextSensitive)) && isContextSensitive(node)) { + if (!node.typeArguments && ((checkMode & (CheckMode.Contextual | CheckMode.SkipContextSensitive)) === (CheckMode.Contextual | CheckMode.SkipContextSensitive)) && isContextSensitive(node)) { skippedGenericFunction(node, checkMode); return resolvingSignature; }