Skip to content

Commit

Permalink
Added custom error message when trying to assign constraint type to g…
Browse files Browse the repository at this point in the history
…eneric type parameter

Fixes microsoft#29049.

This also adds the new message in chained error messages. `typeParameterDiamond4.errors.txt` shows it appearing twice in the "diamond" scenario. I can't tell if this severely increased amount of nested messages is good or bad...?
  • Loading branch information
Josh Goldberg committed Jan 15, 2019
1 parent 4968989 commit 54ede16
Show file tree
Hide file tree
Showing 100 changed files with 889 additions and 130 deletions.
13 changes: 13 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11904,6 +11904,19 @@ namespace ts {
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
}

if (
target.flags & TypeFlags.TypeParameter
&& target.immediateBaseConstraint !== undefined
&& isTypeAssignableTo(source, target.immediateBaseConstraint)
) {
reportError(
Diagnostics._0_is_assignable_to_the_constraint_of_type_2_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2,
sourceType,
targetType,
typeToString(target.immediateBaseConstraint),
);
}

if (!message) {
if (relation === comparableRelation) {
message = Diagnostics.Type_0_is_not_comparable_to_type_1;
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3020,6 +3020,10 @@
"category": "Error",
"code": 5073
},
"'{0}' is assignable to the constraint of type '{2}', but '{1}' could be instantiated with a different subtype of constraint '{2}'.": {
"category": "Error",
"code": 5074
},

"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,30 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'string' is not assignable to type 'T'.
'string' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(62,1): error TS2322: Type '(x: (arg: Base) => Derived) => Base' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U) => T'.
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'Base' is not assignable to type 'T'.
'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(65,1): error TS2322: Type '(x: (arg: Base) => Derived) => (r: Base) => Derived' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U) => (r: T) => U'.
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'Base' is not assignable to type 'T'.
'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(68,1): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U'.
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'Base' is not assignable to type 'T'.
'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(71,1): error TS2322: Type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived' is not assignable to type '<T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: string; bing: number; }) => U) => (r: T) => U'.
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'Base' is not assignable to type 'T'.
'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(74,1): error TS2322: Type '(...x: Derived[]) => Derived' is not assignable to type '<T extends Derived>(...x: T[]) => T'.
Type 'Derived' is not assignable to type 'T'.
'Derived' is assignable to the constraint of type 'Derived', but 'T' could be instantiated with a different subtype of constraint 'Derived'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(77,1): error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '<T extends Base>(x: T, y: T) => T'.
Types of parameters 'y' and 'y' are incompatible.
Type 'T' is not assignable to type '{ foo: string; bar: string; }'.
Expand All @@ -43,6 +49,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
Type 'Base' is missing the following properties from type 'Derived2': baz, bar
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(83,1): error TS2322: Type '(x: Base[], y: Derived[]) => Derived[]' is not assignable to type '<T extends Derived[]>(x: Base[], y: T) => T'.
Type 'Derived[]' is not assignable to type 'T'.
'Derived[]' is assignable to the constraint of type 'Derived[]', but 'T' could be instantiated with a different subtype of constraint 'Derived[]'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures3.ts(85,1): error TS2322: Type '<T>(x: { a: T; b: T; }) => T' is not assignable to type '(x: { a: string; b: number; }) => Object'.
Types of parameters 'x' and 'x' are incompatible.
Type '{ a: string; b: number; }' is not assignable to type '{ a: string; b: string; }'.
Expand Down Expand Up @@ -136,6 +143,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'T'.
!!! error TS2322: 'string' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
var b6: <T extends Base, U extends Derived>(x: (arg: T) => U) => T;
a6 = b6; // ok
b6 = a6; // ok
Expand All @@ -144,6 +152,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
!!! error TS2322: 'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
var b7: <T extends Base, U extends Derived>(x: (arg: T) => U) => (r: T) => U;
a7 = b7; // ok
b7 = a7; // ok
Expand All @@ -152,6 +161,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
!!! error TS2322: 'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
var b8: <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U;
a8 = b8; // ok
b8 = a8; // ok
Expand All @@ -160,6 +170,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
!!! error TS2322: 'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
var b9: <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: string; bing: number }) => U) => (r: T) => U;
a9 = b9; // ok
b9 = a9; // ok
Expand All @@ -168,12 +179,14 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
!!! error TS2322: 'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
var b10: <T extends Derived>(...x: T[]) => T;
a10 = b10; // ok
b10 = a10; // ok
~~~
!!! error TS2322: Type '(...x: Derived[]) => Derived' is not assignable to type '<T extends Derived>(...x: T[]) => T'.
!!! error TS2322: Type 'Derived' is not assignable to type 'T'.
!!! error TS2322: 'Derived' is assignable to the constraint of type 'Derived', but 'T' could be instantiated with a different subtype of constraint 'Derived'.
var b11: <T extends Base>(x: T, y: T) => T;
a11 = b11; // ok
b11 = a11; // ok
Expand All @@ -198,6 +211,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
~~~
!!! error TS2322: Type '(x: Base[], y: Derived[]) => Derived[]' is not assignable to type '<T extends Derived[]>(x: Base[], y: T) => T'.
!!! error TS2322: Type 'Derived[]' is not assignable to type 'T'.
!!! error TS2322: 'Derived[]' is assignable to the constraint of type 'Derived[]', but 'T' could be instantiated with a different subtype of constraint 'Derived[]'.
var b14: <T>(x: { a: T; b: T }) => T;
a14 = b14; // ok
~~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'Base' is not assignable to type 'T'.
'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(52,9): error TS2322: Type '<T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U' is not assignable to type '(x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived'.
Types of parameters 'y' and 'y' are incompatible.
Types of parameters 'arg2' and 'arg2' are incompatible.
Expand All @@ -15,6 +16,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
Types of parameters 'x' and 'x' are incompatible.
Types of parameters 'arg' and 'arg' are incompatible.
Type 'Base' is not assignable to type 'T'.
'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(58,9): error TS2322: Type '(...x: Base[]) => Base' is not assignable to type '<T extends Derived>(...x: T[]) => T'.
Type 'Base' is not assignable to type 'T'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(62,9): error TS2322: Type '(x: { foo: string; }, y: { foo: string; bar: string; }) => Base' is not assignable to type '<T extends Derived>(x: T, y: T) => T'.
Expand Down Expand Up @@ -45,6 +47,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(89,9): error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
Type 'string[]' is not assignable to type 'T[]'.
Type 'string' is not assignable to type 'T'.
'string' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(90,9): error TS2322: Type '<T>(x: T) => T[]' is not assignable to type '<T>(x: T) => string[]'.
Type 'T[]' is not assignable to type 'string[]'.
Type 'T' is not assignable to type 'string'.
Expand All @@ -54,6 +57,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts(96,9): error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
Type 'string[]' is not assignable to type 'T[]'.
Type 'string' is not assignable to type 'T'.
'string' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.


==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures4.ts (15 errors) ====
Expand Down Expand Up @@ -115,6 +119,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
!!! error TS2322: 'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.

var b8: <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: number; }) => U) => (r: T) => U;
a8 = b8; // error, { foo: number } and Base are incompatible
Expand All @@ -131,6 +136,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Types of parameters 'x' and 'x' are incompatible.
!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible.
!!! error TS2322: Type 'Base' is not assignable to type 'T'.
!!! error TS2322: 'Base' is assignable to the constraint of type 'Base', but 'T' could be instantiated with a different subtype of constraint 'Base'.


var b10: <T extends Derived>(...x: T[]) => T;
Expand Down Expand Up @@ -205,6 +211,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'.
!!! error TS2322: Type 'string' is not assignable to type 'T'.
!!! error TS2322: 'string' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
b2 = a2;
~~
!!! error TS2322: Type '<T>(x: T) => T[]' is not assignable to type '<T>(x: T) => string[]'.
Expand All @@ -224,5 +231,6 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Type '<T>(x: T) => string[]' is not assignable to type '<T>(x: T) => T[]'.
!!! error TS2322: Type 'string[]' is not assignable to type 'T[]'.
!!! error TS2322: Type 'string' is not assignable to type 'T'.
!!! error TS2322: 'string' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
Types of property 'foo' are incompatible.
Type 'U' is not assignable to type 'T'.
'U' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(55,1): error TS2322: Type '<T>(x: { a: T; b: T; }) => T[]' is not assignable to type '<U, V>(x: { a: U; b: V; }) => U[]'.
Types of parameters 'x' and 'x' are incompatible.
Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
Types of property 'b' are incompatible.
Type 'V' is not assignable to type 'U'.
'V' is assignable to the constraint of type '{}', but 'U' could be instantiated with a different subtype of constraint '{}'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures5.ts(58,1): error TS2322: Type '<T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type '<U, V>(x: { a: U; b: V; }) => U[]'.
Types of parameters 'x' and 'x' are incompatible.
Type '{ a: U; b: V; }' is not assignable to type '{ a: Base; b: Base; }'.
Expand Down Expand Up @@ -79,6 +81,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type 'U' is not assignable to type 'T'.
!!! error TS2322: 'U' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
var b15: <U, V>(x: { a: U; b: V; }) => U[];
a15 = b15; // ok, T = U, T = V
b15 = a15; // ok
Expand All @@ -88,6 +91,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Type '{ a: U; b: V; }' is not assignable to type '{ a: U; b: U; }'.
!!! error TS2322: Types of property 'b' are incompatible.
!!! error TS2322: Type 'V' is not assignable to type 'U'.
!!! error TS2322: 'V' is assignable to the constraint of type '{}', but 'U' could be instantiated with a different subtype of constraint '{}'.
var b16: <T>(x: { a: T; b: T }) => T[];
a15 = b16; // ok
b15 = a16; // ok
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
Types of property 'foo' are incompatible.
Type 'U' is not assignable to type 'T'.
'U' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures6.ts(42,1): error TS2322: Type '<T extends Base>(x: { a: T; b: T; }) => T[]' is not assignable to type '<T>(x: { a: T; b: T; }) => T[]'.
Types of parameters 'x' and 'x' are incompatible.
Type '{ a: T; b: T; }' is not assignable to type '{ a: Base; b: Base; }'.
Expand Down Expand Up @@ -61,6 +62,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
!!! error TS2322: Type '{ foo: U; bar: U; }' is not assignable to type '{ foo: T; bar: T; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type 'U' is not assignable to type 'T'.
!!! error TS2322: 'U' is assignable to the constraint of type '{}', but 'T' could be instantiated with a different subtype of constraint '{}'.
var b16: <T>(x: { a: T; b: T }) => T[];
x.a16 = b16;
b16 = x.a16;
Expand Down
Loading

0 comments on commit 54ede16

Please sign in to comment.