diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 289a98a4295..91ef12d2a29 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20691,8 +20691,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. - const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); - const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); + const sourceSig = checkMode & SignatureCheckMode.Callback || isInstantiatedGenericParameter(source, i) ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); + const targetSig = checkMode & SignatureCheckMode.Callback || isInstantiatedGenericParameter(target, i) ? undefined : getSingleCallSignature(getNonNullableType(targetType)); const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && getTypeFacts(sourceType, TypeFacts.IsUndefinedOrNull) === getTypeFacts(targetType, TypeFacts.IsUndefinedOrNull); let related = callbacks ? @@ -33486,6 +33486,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); } + function isInstantiatedGenericParameter(signature: Signature, pos: number) { + let type; + return !!(signature.target && (type = tryGetTypeAtPosition(signature.target, pos)) && isGenericType(type)); + } + // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. function getSingleCallSignature(type: Type): Signature | undefined { return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false); diff --git a/tests/baselines/reference/covariantCallbacks.errors.txt b/tests/baselines/reference/covariantCallbacks.errors.txt index 5de161c1ab5..7a9e34234fc 100644 --- a/tests/baselines/reference/covariantCallbacks.errors.txt +++ b/tests/baselines/reference/covariantCallbacks.errors.txt @@ -23,9 +23,18 @@ covariantCallbacks.ts(69,5): error TS2322: Type 'AList4' is not assignable to ty Types of parameters 'cb' and 'cb' are incompatible. Types of parameters 'item' and 'item' are incompatible. Type 'A' is not assignable to type 'B'. +covariantCallbacks.ts(98,1): error TS2322: Type 'SetLike1<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. + Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. + Types of parameters 'x' and 'x' are incompatible. + Type 'unknown' is not assignable to type 'string'. +covariantCallbacks.ts(106,1): error TS2322: Type 'SetLike2<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. + The types returned by 'get()' are incompatible between these types. + Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. + Types of parameters 'x' and 'x' are incompatible. + Type 'unknown' is not assignable to type 'string'. -==== covariantCallbacks.ts (6 errors) ==== +==== covariantCallbacks.ts (8 errors) ==== // Test that callback parameters are related covariantly interface P { @@ -128,4 +137,52 @@ covariantCallbacks.ts(69,5): error TS2322: Type 'AList4' is not assignable to ty !!! error TS2322: Types of parameters 'item' and 'item' are incompatible. !!! error TS2322: Type 'A' is not assignable to type 'B'. } + + // Repro from #51620 + + type Bivar = { set(value: T): void } + + declare let bu: Bivar; + declare let bs: Bivar; + bu = bs; + bs = bu; + + declare let bfu: Bivar<(x: unknown) => void>; + declare let bfs: Bivar<(x: string) => void>; + bfu = bfs; + bfs = bfu; + + type Bivar1 = { set(value: T): void } + type Bivar2 = { set(value: T): void } + + declare let b1fu: Bivar1<(x: unknown) => void>; + declare let b2fs: Bivar2<(x: string) => void>; + b1fu = b2fs; + b2fs = b1fu; + + type SetLike = { set(value: T): void, get(): T } + + declare let sx: SetLike1<(x: unknown) => void>; + declare let sy: SetLike1<(x: string) => void>; + sx = sy; // Error + ~~ +!!! error TS2322: Type 'SetLike1<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. +!!! error TS2322: Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. + sy = sx; + + type SetLike1 = { set(value: T): void, get(): T } + type SetLike2 = { set(value: T): void, get(): T } + + declare let s1: SetLike1<(x: unknown) => void>; + declare let s2: SetLike2<(x: string) => void>; + s1 = s2; // Error + ~~ +!!! error TS2322: Type 'SetLike2<(x: string) => void>' is not assignable to type 'SetLike1<(x: unknown) => void>'. +!!! error TS2322: The types returned by 'get()' are incompatible between these types. +!!! error TS2322: Type '(x: string) => void' is not assignable to type '(x: unknown) => void'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. + s2 = s1; \ No newline at end of file diff --git a/tests/baselines/reference/covariantCallbacks.js b/tests/baselines/reference/covariantCallbacks.js index 38578f1af5c..226e7d3ab55 100644 --- a/tests/baselines/reference/covariantCallbacks.js +++ b/tests/baselines/reference/covariantCallbacks.js @@ -71,6 +71,43 @@ function f14(a: AList4, b: BList4) { a = b; b = a; // Error } + +// Repro from #51620 + +type Bivar = { set(value: T): void } + +declare let bu: Bivar; +declare let bs: Bivar; +bu = bs; +bs = bu; + +declare let bfu: Bivar<(x: unknown) => void>; +declare let bfs: Bivar<(x: string) => void>; +bfu = bfs; +bfs = bfu; + +type Bivar1 = { set(value: T): void } +type Bivar2 = { set(value: T): void } + +declare let b1fu: Bivar1<(x: unknown) => void>; +declare let b2fs: Bivar2<(x: string) => void>; +b1fu = b2fs; +b2fs = b1fu; + +type SetLike = { set(value: T): void, get(): T } + +declare let sx: SetLike1<(x: unknown) => void>; +declare let sy: SetLike1<(x: string) => void>; +sx = sy; // Error +sy = sx; + +type SetLike1 = { set(value: T): void, get(): T } +type SetLike2 = { set(value: T): void, get(): T } + +declare let s1: SetLike1<(x: unknown) => void>; +declare let s2: SetLike2<(x: string) => void>; +s1 = s2; // Error +s2 = s1; //// [covariantCallbacks.js] @@ -101,3 +138,13 @@ function f14(a, b) { a = b; b = a; // Error } +bu = bs; +bs = bu; +bfu = bfs; +bfs = bfu; +b1fu = b2fs; +b2fs = b1fu; +sx = sy; // Error +sy = sx; +s1 = s2; // Error +s2 = s1; diff --git a/tests/baselines/reference/covariantCallbacks.symbols b/tests/baselines/reference/covariantCallbacks.symbols index c710196e50b..ca168fca246 100644 --- a/tests/baselines/reference/covariantCallbacks.symbols +++ b/tests/baselines/reference/covariantCallbacks.symbols @@ -207,3 +207,141 @@ function f14(a: AList4, b: BList4) { >a : Symbol(a, Decl(covariantCallbacks.ts, 66, 13)) } +// Repro from #51620 + +type Bivar = { set(value: T): void } +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 73, 11)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 73, 17)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 73, 22)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 73, 11)) + +declare let bu: Bivar; +>bu : Symbol(bu, Decl(covariantCallbacks.ts, 75, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) + +declare let bs: Bivar; +>bs : Symbol(bs, Decl(covariantCallbacks.ts, 76, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) + +bu = bs; +>bu : Symbol(bu, Decl(covariantCallbacks.ts, 75, 11)) +>bs : Symbol(bs, Decl(covariantCallbacks.ts, 76, 11)) + +bs = bu; +>bs : Symbol(bs, Decl(covariantCallbacks.ts, 76, 11)) +>bu : Symbol(bu, Decl(covariantCallbacks.ts, 75, 11)) + +declare let bfu: Bivar<(x: unknown) => void>; +>bfu : Symbol(bfu, Decl(covariantCallbacks.ts, 80, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 80, 24)) + +declare let bfs: Bivar<(x: string) => void>; +>bfs : Symbol(bfs, Decl(covariantCallbacks.ts, 81, 11)) +>Bivar : Symbol(Bivar, Decl(covariantCallbacks.ts, 69, 1)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 81, 24)) + +bfu = bfs; +>bfu : Symbol(bfu, Decl(covariantCallbacks.ts, 80, 11)) +>bfs : Symbol(bfs, Decl(covariantCallbacks.ts, 81, 11)) + +bfs = bfu; +>bfs : Symbol(bfs, Decl(covariantCallbacks.ts, 81, 11)) +>bfu : Symbol(bfu, Decl(covariantCallbacks.ts, 80, 11)) + +type Bivar1 = { set(value: T): void } +>Bivar1 : Symbol(Bivar1, Decl(covariantCallbacks.ts, 83, 10)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 85, 12)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 85, 18)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 85, 23)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 85, 12)) + +type Bivar2 = { set(value: T): void } +>Bivar2 : Symbol(Bivar2, Decl(covariantCallbacks.ts, 85, 40)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 86, 12)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 86, 18)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 86, 23)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 86, 12)) + +declare let b1fu: Bivar1<(x: unknown) => void>; +>b1fu : Symbol(b1fu, Decl(covariantCallbacks.ts, 88, 11)) +>Bivar1 : Symbol(Bivar1, Decl(covariantCallbacks.ts, 83, 10)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 88, 26)) + +declare let b2fs: Bivar2<(x: string) => void>; +>b2fs : Symbol(b2fs, Decl(covariantCallbacks.ts, 89, 11)) +>Bivar2 : Symbol(Bivar2, Decl(covariantCallbacks.ts, 85, 40)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 89, 26)) + +b1fu = b2fs; +>b1fu : Symbol(b1fu, Decl(covariantCallbacks.ts, 88, 11)) +>b2fs : Symbol(b2fs, Decl(covariantCallbacks.ts, 89, 11)) + +b2fs = b1fu; +>b2fs : Symbol(b2fs, Decl(covariantCallbacks.ts, 89, 11)) +>b1fu : Symbol(b1fu, Decl(covariantCallbacks.ts, 88, 11)) + +type SetLike = { set(value: T): void, get(): T } +>SetLike : Symbol(SetLike, Decl(covariantCallbacks.ts, 91, 12)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 93, 13)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 93, 19)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 93, 24)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 93, 13)) +>get : Symbol(get, Decl(covariantCallbacks.ts, 93, 40)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 93, 13)) + +declare let sx: SetLike1<(x: unknown) => void>; +>sx : Symbol(sx, Decl(covariantCallbacks.ts, 95, 11)) +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 95, 26)) + +declare let sy: SetLike1<(x: string) => void>; +>sy : Symbol(sy, Decl(covariantCallbacks.ts, 96, 11)) +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 96, 26)) + +sx = sy; // Error +>sx : Symbol(sx, Decl(covariantCallbacks.ts, 95, 11)) +>sy : Symbol(sy, Decl(covariantCallbacks.ts, 96, 11)) + +sy = sx; +>sy : Symbol(sy, Decl(covariantCallbacks.ts, 96, 11)) +>sx : Symbol(sx, Decl(covariantCallbacks.ts, 95, 11)) + +type SetLike1 = { set(value: T): void, get(): T } +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 100, 14)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 100, 20)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 100, 25)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 100, 14)) +>get : Symbol(get, Decl(covariantCallbacks.ts, 100, 41)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 100, 14)) + +type SetLike2 = { set(value: T): void, get(): T } +>SetLike2 : Symbol(SetLike2, Decl(covariantCallbacks.ts, 100, 52)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 101, 14)) +>set : Symbol(set, Decl(covariantCallbacks.ts, 101, 20)) +>value : Symbol(value, Decl(covariantCallbacks.ts, 101, 25)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 101, 14)) +>get : Symbol(get, Decl(covariantCallbacks.ts, 101, 41)) +>T : Symbol(T, Decl(covariantCallbacks.ts, 101, 14)) + +declare let s1: SetLike1<(x: unknown) => void>; +>s1 : Symbol(s1, Decl(covariantCallbacks.ts, 103, 11)) +>SetLike1 : Symbol(SetLike1, Decl(covariantCallbacks.ts, 98, 8)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 103, 26)) + +declare let s2: SetLike2<(x: string) => void>; +>s2 : Symbol(s2, Decl(covariantCallbacks.ts, 104, 11)) +>SetLike2 : Symbol(SetLike2, Decl(covariantCallbacks.ts, 100, 52)) +>x : Symbol(x, Decl(covariantCallbacks.ts, 104, 26)) + +s1 = s2; // Error +>s1 : Symbol(s1, Decl(covariantCallbacks.ts, 103, 11)) +>s2 : Symbol(s2, Decl(covariantCallbacks.ts, 104, 11)) + +s2 = s1; +>s2 : Symbol(s2, Decl(covariantCallbacks.ts, 104, 11)) +>s1 : Symbol(s1, Decl(covariantCallbacks.ts, 103, 11)) + diff --git a/tests/baselines/reference/covariantCallbacks.types b/tests/baselines/reference/covariantCallbacks.types index 1b2f082da52..849ff661417 100644 --- a/tests/baselines/reference/covariantCallbacks.types +++ b/tests/baselines/reference/covariantCallbacks.types @@ -170,3 +170,126 @@ function f14(a: AList4, b: BList4) { >a : AList4 } +// Repro from #51620 + +type Bivar = { set(value: T): void } +>Bivar : Bivar +>set : (value: T) => void +>value : T + +declare let bu: Bivar; +>bu : Bivar + +declare let bs: Bivar; +>bs : Bivar + +bu = bs; +>bu = bs : Bivar +>bu : Bivar +>bs : Bivar + +bs = bu; +>bs = bu : Bivar +>bs : Bivar +>bu : Bivar + +declare let bfu: Bivar<(x: unknown) => void>; +>bfu : Bivar<(x: unknown) => void> +>x : unknown + +declare let bfs: Bivar<(x: string) => void>; +>bfs : Bivar<(x: string) => void> +>x : string + +bfu = bfs; +>bfu = bfs : Bivar<(x: string) => void> +>bfu : Bivar<(x: unknown) => void> +>bfs : Bivar<(x: string) => void> + +bfs = bfu; +>bfs = bfu : Bivar<(x: unknown) => void> +>bfs : Bivar<(x: string) => void> +>bfu : Bivar<(x: unknown) => void> + +type Bivar1 = { set(value: T): void } +>Bivar1 : Bivar1 +>set : (value: T) => void +>value : T + +type Bivar2 = { set(value: T): void } +>Bivar2 : Bivar2 +>set : (value: T) => void +>value : T + +declare let b1fu: Bivar1<(x: unknown) => void>; +>b1fu : Bivar1<(x: unknown) => void> +>x : unknown + +declare let b2fs: Bivar2<(x: string) => void>; +>b2fs : Bivar2<(x: string) => void> +>x : string + +b1fu = b2fs; +>b1fu = b2fs : Bivar2<(x: string) => void> +>b1fu : Bivar1<(x: unknown) => void> +>b2fs : Bivar2<(x: string) => void> + +b2fs = b1fu; +>b2fs = b1fu : Bivar1<(x: unknown) => void> +>b2fs : Bivar2<(x: string) => void> +>b1fu : Bivar1<(x: unknown) => void> + +type SetLike = { set(value: T): void, get(): T } +>SetLike : SetLike +>set : (value: T) => void +>value : T +>get : () => T + +declare let sx: SetLike1<(x: unknown) => void>; +>sx : SetLike1<(x: unknown) => void> +>x : unknown + +declare let sy: SetLike1<(x: string) => void>; +>sy : SetLike1<(x: string) => void> +>x : string + +sx = sy; // Error +>sx = sy : SetLike1<(x: string) => void> +>sx : SetLike1<(x: unknown) => void> +>sy : SetLike1<(x: string) => void> + +sy = sx; +>sy = sx : SetLike1<(x: unknown) => void> +>sy : SetLike1<(x: string) => void> +>sx : SetLike1<(x: unknown) => void> + +type SetLike1 = { set(value: T): void, get(): T } +>SetLike1 : SetLike1 +>set : (value: T) => void +>value : T +>get : () => T + +type SetLike2 = { set(value: T): void, get(): T } +>SetLike2 : SetLike2 +>set : (value: T) => void +>value : T +>get : () => T + +declare let s1: SetLike1<(x: unknown) => void>; +>s1 : SetLike1<(x: unknown) => void> +>x : unknown + +declare let s2: SetLike2<(x: string) => void>; +>s2 : SetLike2<(x: string) => void> +>x : string + +s1 = s2; // Error +>s1 = s2 : SetLike2<(x: string) => void> +>s1 : SetLike1<(x: unknown) => void> +>s2 : SetLike2<(x: string) => void> + +s2 = s1; +>s2 = s1 : SetLike1<(x: unknown) => void> +>s2 : SetLike2<(x: string) => void> +>s1 : SetLike1<(x: unknown) => void> + diff --git a/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt b/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt index 6e9abea9199..5fd2927b274 100644 --- a/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt +++ b/tests/baselines/reference/genericCallWithGenericSignatureArguments3.errors.txt @@ -1,6 +1,7 @@ genericCallWithGenericSignatureArguments3.ts(32,19): error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => 1' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => 1'. Types of parameters 'a1' and 'x' are incompatible. - Type 'boolean' is not assignable to type 'string'. + Type '(a: string) => boolean' is not assignable to type '(y: string) => string'. + Type 'boolean' is not assignable to type 'string'. genericCallWithGenericSignatureArguments3.ts(33,69): error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => 1'. Type 'number' is not assignable to type '(n: Object) => 1'. @@ -41,7 +42,8 @@ genericCallWithGenericSignatureArguments3.ts(33,69): error TS2345: Argument of t ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => 1' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => 1'. !!! error TS2345: Types of parameters 'a1' and 'x' are incompatible. -!!! error TS2345: Type 'boolean' is not assignable to type 'string'. +!!! error TS2345: Type '(a: string) => boolean' is not assignable to type '(y: string) => string'. +!!! error TS2345: Type 'boolean' is not assignable to type 'string'. var r12 = foo2(x, (a1: (y: string) => boolean) => (n: Object) => 1, (a2: (z: string) => boolean) => 2); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => 1'. diff --git a/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts b/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts index 4f3e7ecda0d..4f747be593f 100644 --- a/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts +++ b/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/covariantCallbacks.ts @@ -71,3 +71,40 @@ function f14(a: AList4, b: BList4) { a = b; b = a; // Error } + +// Repro from #51620 + +type Bivar = { set(value: T): void } + +declare let bu: Bivar; +declare let bs: Bivar; +bu = bs; +bs = bu; + +declare let bfu: Bivar<(x: unknown) => void>; +declare let bfs: Bivar<(x: string) => void>; +bfu = bfs; +bfs = bfu; + +type Bivar1 = { set(value: T): void } +type Bivar2 = { set(value: T): void } + +declare let b1fu: Bivar1<(x: unknown) => void>; +declare let b2fs: Bivar2<(x: string) => void>; +b1fu = b2fs; +b2fs = b1fu; + +type SetLike = { set(value: T): void, get(): T } + +declare let sx: SetLike1<(x: unknown) => void>; +declare let sy: SetLike1<(x: string) => void>; +sx = sy; // Error +sy = sx; + +type SetLike1 = { set(value: T): void, get(): T } +type SetLike2 = { set(value: T): void, get(): T } + +declare let s1: SetLike1<(x: unknown) => void>; +declare let s2: SetLike2<(x: string) => void>; +s1 = s2; // Error +s2 = s1;