From 80491ebd64d81ba9d785d9cf00963104247c036f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 22 Mar 2024 19:51:00 +0100 Subject: [PATCH 1/7] Improve logic that chooses co- vs. contra-variant inferences --- src/compiler/checker.ts | 4 +- .../coAndContraVariantInferences6.symbols | 77 +++++++++++++++++++ .../coAndContraVariantInferences6.types | 74 ++++++++++++++++++ .../compiler/coAndContraVariantInferences6.ts | 28 +++++++ 4 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/coAndContraVariantInferences6.symbols create mode 100644 tests/baselines/reference/coAndContraVariantInferences6.types create mode 100644 tests/cases/compiler/coAndContraVariantInferences6.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ad13bd597db39..153a664a4a043 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26465,10 +26465,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and has inferences that would conflict. Otherwise, we prefer the contra-variant inference. const preferCovariantType = inferredCovariantType && (!inferredContravariantType || !(inferredCovariantType.flags & TypeFlags.Never) && - some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) && + some(inference.contraCandidates, t => isTypeAssignableTo(inferredCovariantType, t)) && every(context.inferences, other => other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter || - every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)))); + every(other.candidates, t => isTypeAssignableTo(t, inferredCovariantType)))); inferredType = preferCovariantType ? inferredCovariantType : inferredContravariantType; fallbackType = preferCovariantType ? inferredContravariantType : inferredCovariantType; } diff --git a/tests/baselines/reference/coAndContraVariantInferences6.symbols b/tests/baselines/reference/coAndContraVariantInferences6.symbols new file mode 100644 index 0000000000000..77b2f03a0b9cf --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences6.symbols @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/coAndContraVariantInferences6.ts] //// + +=== coAndContraVariantInferences6.ts === +type Request = { +>Request : Symbol(Request, Decl(coAndContraVariantInferences6.ts, 0, 0)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 0, 13)) +>Schema : Symbol(Schema, Decl(coAndContraVariantInferences6.ts, 2, 2)) + + query: TSchema["query"]; +>query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 0, 40)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 0, 13)) + +}; + +type Schema = { query?: unknown; body?: unknown }; +>Schema : Symbol(Schema, Decl(coAndContraVariantInferences6.ts, 2, 2)) +>query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 4, 15)) +>body : Symbol(body, Decl(coAndContraVariantInferences6.ts, 4, 32)) + +declare function route(obj: { +>route : Symbol(route, Decl(coAndContraVariantInferences6.ts, 4, 50)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) +>Schema : Symbol(Schema, Decl(coAndContraVariantInferences6.ts, 2, 2)) +>obj : Symbol(obj, Decl(coAndContraVariantInferences6.ts, 6, 47)) + + pre: (a: TSchema) => void; +>pre : Symbol(pre, Decl(coAndContraVariantInferences6.ts, 6, 53)) +>a : Symbol(a, Decl(coAndContraVariantInferences6.ts, 7, 8)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) + + schema: TSchema; +>schema : Symbol(schema, Decl(coAndContraVariantInferences6.ts, 7, 28)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) + + handle: (req: Request) => void; +>handle : Symbol(handle, Decl(coAndContraVariantInferences6.ts, 8, 18)) +>req : Symbol(req, Decl(coAndContraVariantInferences6.ts, 9, 11)) +>Request : Symbol(Request, Decl(coAndContraVariantInferences6.ts, 0, 0)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) + +}): void; + +const validate = (_: { query?: unknown; body?: unknown }) => {}; +>validate : Symbol(validate, Decl(coAndContraVariantInferences6.ts, 12, 5)) +>_ : Symbol(_, Decl(coAndContraVariantInferences6.ts, 12, 18)) +>query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 12, 22)) +>body : Symbol(body, Decl(coAndContraVariantInferences6.ts, 12, 39)) + +route({ +>route : Symbol(route, Decl(coAndContraVariantInferences6.ts, 4, 50)) + + pre: validate, +>pre : Symbol(pre, Decl(coAndContraVariantInferences6.ts, 14, 7)) +>validate : Symbol(validate, Decl(coAndContraVariantInferences6.ts, 12, 5)) + + schema: { +>schema : Symbol(schema, Decl(coAndContraVariantInferences6.ts, 15, 16)) + + query: "", +>query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 16, 11)) + + }, + handle: (req) => { +>handle : Symbol(handle, Decl(coAndContraVariantInferences6.ts, 18, 4)) +>req : Symbol(req, Decl(coAndContraVariantInferences6.ts, 19, 11)) + + const test: string = req.query; +>test : Symbol(test, Decl(coAndContraVariantInferences6.ts, 20, 9)) +>req.query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 0, 40)) +>req : Symbol(req, Decl(coAndContraVariantInferences6.ts, 19, 11)) +>query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 0, 40)) + + }, +}); + +export {}; + diff --git a/tests/baselines/reference/coAndContraVariantInferences6.types b/tests/baselines/reference/coAndContraVariantInferences6.types new file mode 100644 index 0000000000000..b3ceef258512f --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences6.types @@ -0,0 +1,74 @@ +//// [tests/cases/compiler/coAndContraVariantInferences6.ts] //// + +=== coAndContraVariantInferences6.ts === +type Request = { +>Request : Request + + query: TSchema["query"]; +>query : TSchema["query"] + +}; + +type Schema = { query?: unknown; body?: unknown }; +>Schema : { query?: unknown; body?: unknown; } +>query : unknown +>body : unknown + +declare function route(obj: { +>route : (obj: { pre: (a: TSchema) => void; schema: TSchema; handle: (req: Request) => void;}) => void +>obj : { pre: (a: TSchema) => void; schema: TSchema; handle: (req: Request) => void; } + + pre: (a: TSchema) => void; +>pre : (a: TSchema) => void +>a : TSchema + + schema: TSchema; +>schema : TSchema + + handle: (req: Request) => void; +>handle : (req: Request) => void +>req : Request + +}): void; + +const validate = (_: { query?: unknown; body?: unknown }) => {}; +>validate : (_: { query?: unknown; body?: unknown;}) => void +>(_: { query?: unknown; body?: unknown }) => {} : (_: { query?: unknown; body?: unknown;}) => void +>_ : { query?: unknown; body?: unknown; } +>query : unknown +>body : unknown + +route({ +>route({ pre: validate, schema: { query: "", }, handle: (req) => { const test: string = req.query; },}) : void +>route : (obj: { pre: (a: TSchema) => void; schema: TSchema; handle: (req: Request) => void; }) => void +>{ pre: validate, schema: { query: "", }, handle: (req) => { const test: string = req.query; },} : { pre: (_: { query?: unknown; body?: unknown; }) => void; schema: { query: string; }; handle: (req: Request<{ query: string; }>) => void; } + + pre: validate, +>pre : (_: { query?: unknown; body?: unknown; }) => void +>validate : (_: { query?: unknown; body?: unknown; }) => void + + schema: { +>schema : { query: string; } +>{ query: "", } : { query: string; } + + query: "", +>query : string +>"" : "" + + }, + handle: (req) => { +>handle : (req: Request<{ query: string; }>) => void +>(req) => { const test: string = req.query; } : (req: Request<{ query: string; }>) => void +>req : Request<{ query: string; }> + + const test: string = req.query; +>test : string +>req.query : string +>req : Request<{ query: string; }> +>query : string + + }, +}); + +export {}; + diff --git a/tests/cases/compiler/coAndContraVariantInferences6.ts b/tests/cases/compiler/coAndContraVariantInferences6.ts new file mode 100644 index 0000000000000..a54eb8c0eade4 --- /dev/null +++ b/tests/cases/compiler/coAndContraVariantInferences6.ts @@ -0,0 +1,28 @@ +// @strict: true +// @noEmit: true + +type Request = { + query: TSchema["query"]; +}; + +type Schema = { query?: unknown; body?: unknown }; + +declare function route(obj: { + pre: (a: TSchema) => void; + schema: TSchema; + handle: (req: Request) => void; +}): void; + +const validate = (_: { query?: unknown; body?: unknown }) => {}; + +route({ + pre: validate, + schema: { + query: "", + }, + handle: (req) => { + const test: string = req.query; + }, +}); + +export {}; From f78cea6e939574341e226bfbbbaec00de5c1e82a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 23 Mar 2024 10:14:44 +0100 Subject: [PATCH 2/7] rename test file --- .../coAndContraVariantInferences6.symbols | 77 ------------------- .../coAndContraVariantInferences7.symbols | 77 +++++++++++++++++++ ...es => coAndContraVariantInferences7.types} | 4 +- ...s6.ts => coAndContraVariantInferences7.ts} | 0 4 files changed, 79 insertions(+), 79 deletions(-) delete mode 100644 tests/baselines/reference/coAndContraVariantInferences6.symbols create mode 100644 tests/baselines/reference/coAndContraVariantInferences7.symbols rename tests/baselines/reference/{coAndContraVariantInferences6.types => coAndContraVariantInferences7.types} (92%) rename tests/cases/compiler/{coAndContraVariantInferences6.ts => coAndContraVariantInferences7.ts} (100%) diff --git a/tests/baselines/reference/coAndContraVariantInferences6.symbols b/tests/baselines/reference/coAndContraVariantInferences6.symbols deleted file mode 100644 index 77b2f03a0b9cf..0000000000000 --- a/tests/baselines/reference/coAndContraVariantInferences6.symbols +++ /dev/null @@ -1,77 +0,0 @@ -//// [tests/cases/compiler/coAndContraVariantInferences6.ts] //// - -=== coAndContraVariantInferences6.ts === -type Request = { ->Request : Symbol(Request, Decl(coAndContraVariantInferences6.ts, 0, 0)) ->TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 0, 13)) ->Schema : Symbol(Schema, Decl(coAndContraVariantInferences6.ts, 2, 2)) - - query: TSchema["query"]; ->query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 0, 40)) ->TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 0, 13)) - -}; - -type Schema = { query?: unknown; body?: unknown }; ->Schema : Symbol(Schema, Decl(coAndContraVariantInferences6.ts, 2, 2)) ->query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 4, 15)) ->body : Symbol(body, Decl(coAndContraVariantInferences6.ts, 4, 32)) - -declare function route(obj: { ->route : Symbol(route, Decl(coAndContraVariantInferences6.ts, 4, 50)) ->TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) ->Schema : Symbol(Schema, Decl(coAndContraVariantInferences6.ts, 2, 2)) ->obj : Symbol(obj, Decl(coAndContraVariantInferences6.ts, 6, 47)) - - pre: (a: TSchema) => void; ->pre : Symbol(pre, Decl(coAndContraVariantInferences6.ts, 6, 53)) ->a : Symbol(a, Decl(coAndContraVariantInferences6.ts, 7, 8)) ->TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) - - schema: TSchema; ->schema : Symbol(schema, Decl(coAndContraVariantInferences6.ts, 7, 28)) ->TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) - - handle: (req: Request) => void; ->handle : Symbol(handle, Decl(coAndContraVariantInferences6.ts, 8, 18)) ->req : Symbol(req, Decl(coAndContraVariantInferences6.ts, 9, 11)) ->Request : Symbol(Request, Decl(coAndContraVariantInferences6.ts, 0, 0)) ->TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences6.ts, 6, 23)) - -}): void; - -const validate = (_: { query?: unknown; body?: unknown }) => {}; ->validate : Symbol(validate, Decl(coAndContraVariantInferences6.ts, 12, 5)) ->_ : Symbol(_, Decl(coAndContraVariantInferences6.ts, 12, 18)) ->query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 12, 22)) ->body : Symbol(body, Decl(coAndContraVariantInferences6.ts, 12, 39)) - -route({ ->route : Symbol(route, Decl(coAndContraVariantInferences6.ts, 4, 50)) - - pre: validate, ->pre : Symbol(pre, Decl(coAndContraVariantInferences6.ts, 14, 7)) ->validate : Symbol(validate, Decl(coAndContraVariantInferences6.ts, 12, 5)) - - schema: { ->schema : Symbol(schema, Decl(coAndContraVariantInferences6.ts, 15, 16)) - - query: "", ->query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 16, 11)) - - }, - handle: (req) => { ->handle : Symbol(handle, Decl(coAndContraVariantInferences6.ts, 18, 4)) ->req : Symbol(req, Decl(coAndContraVariantInferences6.ts, 19, 11)) - - const test: string = req.query; ->test : Symbol(test, Decl(coAndContraVariantInferences6.ts, 20, 9)) ->req.query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 0, 40)) ->req : Symbol(req, Decl(coAndContraVariantInferences6.ts, 19, 11)) ->query : Symbol(query, Decl(coAndContraVariantInferences6.ts, 0, 40)) - - }, -}); - -export {}; - diff --git a/tests/baselines/reference/coAndContraVariantInferences7.symbols b/tests/baselines/reference/coAndContraVariantInferences7.symbols new file mode 100644 index 0000000000000..0d25446e6ae16 --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences7.symbols @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/coAndContraVariantInferences7.ts] //// + +=== coAndContraVariantInferences7.ts === +type Request = { +>Request : Symbol(Request, Decl(coAndContraVariantInferences7.ts, 0, 0)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences7.ts, 0, 13)) +>Schema : Symbol(Schema, Decl(coAndContraVariantInferences7.ts, 2, 2)) + + query: TSchema["query"]; +>query : Symbol(query, Decl(coAndContraVariantInferences7.ts, 0, 40)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences7.ts, 0, 13)) + +}; + +type Schema = { query?: unknown; body?: unknown }; +>Schema : Symbol(Schema, Decl(coAndContraVariantInferences7.ts, 2, 2)) +>query : Symbol(query, Decl(coAndContraVariantInferences7.ts, 4, 15)) +>body : Symbol(body, Decl(coAndContraVariantInferences7.ts, 4, 32)) + +declare function route(obj: { +>route : Symbol(route, Decl(coAndContraVariantInferences7.ts, 4, 50)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences7.ts, 6, 23)) +>Schema : Symbol(Schema, Decl(coAndContraVariantInferences7.ts, 2, 2)) +>obj : Symbol(obj, Decl(coAndContraVariantInferences7.ts, 6, 47)) + + pre: (a: TSchema) => void; +>pre : Symbol(pre, Decl(coAndContraVariantInferences7.ts, 6, 53)) +>a : Symbol(a, Decl(coAndContraVariantInferences7.ts, 7, 8)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences7.ts, 6, 23)) + + schema: TSchema; +>schema : Symbol(schema, Decl(coAndContraVariantInferences7.ts, 7, 28)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences7.ts, 6, 23)) + + handle: (req: Request) => void; +>handle : Symbol(handle, Decl(coAndContraVariantInferences7.ts, 8, 18)) +>req : Symbol(req, Decl(coAndContraVariantInferences7.ts, 9, 11)) +>Request : Symbol(Request, Decl(coAndContraVariantInferences7.ts, 0, 0)) +>TSchema : Symbol(TSchema, Decl(coAndContraVariantInferences7.ts, 6, 23)) + +}): void; + +const validate = (_: { query?: unknown; body?: unknown }) => {}; +>validate : Symbol(validate, Decl(coAndContraVariantInferences7.ts, 12, 5)) +>_ : Symbol(_, Decl(coAndContraVariantInferences7.ts, 12, 18)) +>query : Symbol(query, Decl(coAndContraVariantInferences7.ts, 12, 22)) +>body : Symbol(body, Decl(coAndContraVariantInferences7.ts, 12, 39)) + +route({ +>route : Symbol(route, Decl(coAndContraVariantInferences7.ts, 4, 50)) + + pre: validate, +>pre : Symbol(pre, Decl(coAndContraVariantInferences7.ts, 14, 7)) +>validate : Symbol(validate, Decl(coAndContraVariantInferences7.ts, 12, 5)) + + schema: { +>schema : Symbol(schema, Decl(coAndContraVariantInferences7.ts, 15, 16)) + + query: "", +>query : Symbol(query, Decl(coAndContraVariantInferences7.ts, 16, 11)) + + }, + handle: (req) => { +>handle : Symbol(handle, Decl(coAndContraVariantInferences7.ts, 18, 4)) +>req : Symbol(req, Decl(coAndContraVariantInferences7.ts, 19, 11)) + + const test: string = req.query; +>test : Symbol(test, Decl(coAndContraVariantInferences7.ts, 20, 9)) +>req.query : Symbol(query, Decl(coAndContraVariantInferences7.ts, 0, 40)) +>req : Symbol(req, Decl(coAndContraVariantInferences7.ts, 19, 11)) +>query : Symbol(query, Decl(coAndContraVariantInferences7.ts, 0, 40)) + + }, +}); + +export {}; + diff --git a/tests/baselines/reference/coAndContraVariantInferences6.types b/tests/baselines/reference/coAndContraVariantInferences7.types similarity index 92% rename from tests/baselines/reference/coAndContraVariantInferences6.types rename to tests/baselines/reference/coAndContraVariantInferences7.types index b3ceef258512f..63e05e54ff551 100644 --- a/tests/baselines/reference/coAndContraVariantInferences6.types +++ b/tests/baselines/reference/coAndContraVariantInferences7.types @@ -1,6 +1,6 @@ -//// [tests/cases/compiler/coAndContraVariantInferences6.ts] //// +//// [tests/cases/compiler/coAndContraVariantInferences7.ts] //// -=== coAndContraVariantInferences6.ts === +=== coAndContraVariantInferences7.ts === type Request = { >Request : Request diff --git a/tests/cases/compiler/coAndContraVariantInferences6.ts b/tests/cases/compiler/coAndContraVariantInferences7.ts similarity index 100% rename from tests/cases/compiler/coAndContraVariantInferences6.ts rename to tests/cases/compiler/coAndContraVariantInferences7.ts From 237aba6fe4a3c95be026326da2cb6b1cbf2dab1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 23 Mar 2024 10:20:46 +0100 Subject: [PATCH 3/7] ignore covariant any inferences when contravariant candidates are available --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 153a664a4a043..7ce27427853cc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26463,8 +26463,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // all co-variant inferences are subtypes of it (i.e. it isn't one of a conflicting set of candidates), it is // a subtype of some contra-variant inference, and no other type parameter is constrained to this type parameter // and has inferences that would conflict. Otherwise, we prefer the contra-variant inference. + // Similarly ignore co-variant `any` inference when both are available as almost everything is assignable to it + // and it would spoil the overall inference. const preferCovariantType = inferredCovariantType && (!inferredContravariantType || - !(inferredCovariantType.flags & TypeFlags.Never) && + !(inferredCovariantType.flags & (TypeFlags.Never | TypeFlags.Any)) && some(inference.contraCandidates, t => isTypeAssignableTo(inferredCovariantType, t)) && every(context.inferences, other => other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter || From b715e323b6d0b6331ad791bea2e25a2f3dc6303c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 8 May 2024 18:41:24 +0200 Subject: [PATCH 4/7] add an extra test case --- .../coAndContraVariantInferences8.symbols | 29 +++++++++++++ .../coAndContraVariantInferences8.types | 43 +++++++++++++++++++ .../compiler/coAndContraVariantInferences8.ts | 14 ++++++ 3 files changed, 86 insertions(+) create mode 100644 tests/baselines/reference/coAndContraVariantInferences8.symbols create mode 100644 tests/baselines/reference/coAndContraVariantInferences8.types create mode 100644 tests/cases/compiler/coAndContraVariantInferences8.ts diff --git a/tests/baselines/reference/coAndContraVariantInferences8.symbols b/tests/baselines/reference/coAndContraVariantInferences8.symbols new file mode 100644 index 0000000000000..7f5fb8b66e393 --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences8.symbols @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/coAndContraVariantInferences8.ts] //// + +=== coAndContraVariantInferences8.ts === +// https://github.com/microsoft/TypeScript/issues/58468 + +declare const fn: (() => void) | ((a: number) => void); +>fn : Symbol(fn, Decl(coAndContraVariantInferences8.ts, 2, 13)) +>a : Symbol(a, Decl(coAndContraVariantInferences8.ts, 2, 35)) + +declare const x: number; +>x : Symbol(x, Decl(coAndContraVariantInferences8.ts, 4, 13)) + +declare const y: any; +>y : Symbol(y, Decl(coAndContraVariantInferences8.ts, 5, 13)) + +fn.call(null, x); +>fn.call : Symbol(CallableFunction.call, Decl(lib.es5.d.ts, --, --)) +>fn : Symbol(fn, Decl(coAndContraVariantInferences8.ts, 2, 13)) +>call : Symbol(CallableFunction.call, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(coAndContraVariantInferences8.ts, 4, 13)) + +fn.call(null, y); +>fn.call : Symbol(CallableFunction.call, Decl(lib.es5.d.ts, --, --)) +>fn : Symbol(fn, Decl(coAndContraVariantInferences8.ts, 2, 13)) +>call : Symbol(CallableFunction.call, Decl(lib.es5.d.ts, --, --)) +>y : Symbol(y, Decl(coAndContraVariantInferences8.ts, 5, 13)) + +export {}; + diff --git a/tests/baselines/reference/coAndContraVariantInferences8.types b/tests/baselines/reference/coAndContraVariantInferences8.types new file mode 100644 index 0000000000000..2873dc20fe92a --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences8.types @@ -0,0 +1,43 @@ +//// [tests/cases/compiler/coAndContraVariantInferences8.ts] //// + +=== coAndContraVariantInferences8.ts === +// https://github.com/microsoft/TypeScript/issues/58468 + +declare const fn: (() => void) | ((a: number) => void); +>fn : (() => void) | ((a: number) => void) +> : ^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ +>a : number +> : ^^^^^^ + +declare const x: number; +>x : number +> : ^^^^^^ + +declare const y: any; +>y : any + +fn.call(null, x); +>fn.call(null, x) : void +> : ^^^^ +>fn.call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R +> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +>fn : (() => void) | ((a: number) => void) +> : ^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ +>call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R +> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +>x : number +> : ^^^^^^ + +fn.call(null, y); +>fn.call(null, y) : void +> : ^^^^ +>fn.call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R +> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +>fn : (() => void) | ((a: number) => void) +> : ^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ +>call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R +> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +>y : any + +export {}; + diff --git a/tests/cases/compiler/coAndContraVariantInferences8.ts b/tests/cases/compiler/coAndContraVariantInferences8.ts new file mode 100644 index 0000000000000..ab13ce7c1d909 --- /dev/null +++ b/tests/cases/compiler/coAndContraVariantInferences8.ts @@ -0,0 +1,14 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/58468 + +declare const fn: (() => void) | ((a: number) => void); + +declare const x: number; +declare const y: any; + +fn.call(null, x); +fn.call(null, y); + +export {}; From 2226e0ba430a3aa414d7de223fbf0ac17d0ca14e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 14 Jun 2024 23:13:57 +0200 Subject: [PATCH 5/7] tweak comment --- 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 3d9e2e8e1a845..db1cc6d38ca7f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26336,8 +26336,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const inferredContravariantType = inference.contraCandidates ? getContravariantInference(inference) : undefined; if (inferredCovariantType || inferredContravariantType) { // If we have both co- and contra-variant inferences, we prefer the co-variant inference if it is not 'never', - // all co-variant inferences are subtypes of it (i.e. it isn't one of a conflicting set of candidates), it is - // a subtype of some contra-variant inference, and no other type parameter is constrained to this type parameter + // all co-variant inferences are assignable to it (i.e. it isn't one of a conflicting set of candidates), it is + // assignable to some contra-variant inference, and no other type parameter is constrained to this type parameter // and has inferences that would conflict. Otherwise, we prefer the contra-variant inference. // Similarly ignore co-variant `any` inference when both are available as almost everything is assignable to it // and it would spoil the overall inference. From 169d720b7e7cea509b019e1a5c309e5e8075d2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 14 Jun 2024 23:17:14 +0200 Subject: [PATCH 6/7] update baseline --- .../reference/coAndContraVariantInferences8.types | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/coAndContraVariantInferences8.types b/tests/baselines/reference/coAndContraVariantInferences8.types index 2873dc20fe92a..95eae412d8b2d 100644 --- a/tests/baselines/reference/coAndContraVariantInferences8.types +++ b/tests/baselines/reference/coAndContraVariantInferences8.types @@ -20,11 +20,11 @@ fn.call(null, x); >fn.call(null, x) : void > : ^^^^ >fn.call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R -> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ >fn : (() => void) | ((a: number) => void) -> : ^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ +> : ^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ >call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R -> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ >x : number > : ^^^^^^ @@ -32,11 +32,11 @@ fn.call(null, y); >fn.call(null, y) : void > : ^^^^ >fn.call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R -> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ >fn : (() => void) | ((a: number) => void) -> : ^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ +> : ^^^^^^^ ^^^^^^ ^^ ^^^^^ ^ >call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R -> : ^ ^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^^ +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ >y : any export {}; From 91d69a1f8e575e7464d461c74f7185c2701cb8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 15 Jun 2024 08:17:31 +0200 Subject: [PATCH 7/7] update a baseline --- tests/baselines/reference/coAndContraVariantInferences7.types | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/coAndContraVariantInferences7.types b/tests/baselines/reference/coAndContraVariantInferences7.types index b5d121086ee89..789394b5b41d5 100644 --- a/tests/baselines/reference/coAndContraVariantInferences7.types +++ b/tests/baselines/reference/coAndContraVariantInferences7.types @@ -21,7 +21,7 @@ type Schema = { query?: unknown; body?: unknown }; declare function route(obj: { >route : (obj: { pre: (a: TSchema) => void; schema: TSchema; handle: (req: Request) => void; }) => void -> : ^ ^^^^^^^^^^^^^^^^^ ^^ ^^^^^ +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ >obj : { pre: (a: TSchema) => void; schema: TSchema; handle: (req: Request) => void; } > : ^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ ^^^ @@ -59,7 +59,7 @@ route({ >route({ pre: validate, schema: { query: "", }, handle: (req) => { const test: string = req.query; },}) : void > : ^^^^ >route : (obj: { pre: (a: TSchema) => void; schema: TSchema; handle: (req: Request) => void; }) => void -> : ^ ^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^ +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ >{ pre: validate, schema: { query: "", }, handle: (req) => { const test: string = req.query; },} : { pre: (_: { query?: unknown; body?: unknown; }) => void; schema: { query: string; }; handle: (req: Request<{ query: string; }>) => void; } > : ^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^