Merge pull request #30916 from jack-williams/array-elaboration

Elaborate array and tuple relation errors
This commit is contained in:
Daniel Rosenwasser 2019-04-15 14:00:22 -07:00 committed by GitHub
commit 3dc78b6f3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 322 additions and 23 deletions

View file

@ -12241,6 +12241,40 @@ namespace ts {
}
}
/**
* Try and elaborate array and tuple errors. Returns false
* if we have found an elaboration, or we should ignore
* any other elaborations when relating the `source` and
* `target` types.
*
* @param source
* @param target
* @param reportErrors
*/
function tryElaborateArrayLikeErrors(source: Type, target: Type, reportErrors: boolean): boolean {
if (isTupleLikeType(source)) {
const sourceTuple: TupleType | undefined = (source as TupleTypeReference).target;
if (sourceTuple && sourceTuple.readonly && isArrayOrTupleLikeType(target) &&
(!isReadonlyArrayType(target) || isTupleType(target) && !target.target.readonly)) {
if (reportErrors) {
reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target));
}
return false;
}
return isArrayLikeType(target);
}
if (isTupleLikeType(target)) {
return isArrayLikeType(source);
}
if (isReadonlyArrayType(source) && isArrayType(target) && !isReadonlyArrayType(target)) {
if (reportErrors) {
reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target));
}
return false;
}
return true;
}
function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
if (!(type.flags & TypeFlags.UnionOrIntersection)) {
return false;
@ -12413,6 +12447,9 @@ namespace ts {
if (!result && reportErrors) {
const maybeSuppress = suppressNextError;
suppressNextError = false;
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
tryElaborateArrayLikeErrors(source, target, reportErrors);
}
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) {
tryElaborateErrorsForPrimitivesAndObjects(source, target);
}
@ -13143,11 +13180,13 @@ namespace ts {
associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName));
}
}
else if (props.length > 5) { // arbitrary cutoff for too-long list form
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4);
}
else {
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", "));
else if (tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ false)) {
if (props.length > 5) { // arbitrary cutoff for too-long list form
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4);
}
else {
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", "));
}
}
}
return Ternary.False;

View file

@ -2947,7 +2947,11 @@
"category": "Error",
"code": 4103
},
"The type '{0}' is 'readonly' and cannot be assigned to the mutable type '{1}'.": {
"category": "Error",
"code": 4104
},
"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001

View file

@ -1,5 +1,4 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts(17,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
Type 'FooIterator' is missing the following properties from type '[any, any]': 0, 1, length, pop, and 26 more.
==== tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts (1 errors) ====
@ -21,5 +20,4 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts(17,5): error
function fun([a, b]) { }
fun(new FooIterator);
~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
!!! error TS2345: Type 'FooIterator' is missing the following properties from type '[any, any]': 0, 1, length, pop, and 26 more.
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.

View file

@ -1,5 +1,4 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern13.ts(17,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, ...any[]]'.
Type 'FooIterator' is missing the following properties from type '[any, ...any[]]': 0, length, pop, push, and 25 more.
==== tests/cases/conformance/es6/destructuring/iterableArrayPattern13.ts (1 errors) ====
@ -21,5 +20,4 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern13.ts(17,5): error
function fun([a, ...b]) { }
fun(new FooIterator);
~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, ...any[]]'.
!!! error TS2345: Type 'FooIterator' is missing the following properties from type '[any, ...any[]]': 0, length, pop, push, and 25 more.
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, ...any[]]'.

View file

@ -1,5 +1,4 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts(2,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[Bar, Bar]'.
Type 'FooIterator' is missing the following properties from type '[Bar, Bar]': 0, 1, length, pop, and 26 more.
tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts(2,12): error TS2449: Class 'FooIteratorIterator' used before its declaration.
@ -8,7 +7,6 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts(2,12): error
fun(...new FooIteratorIterator);
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[Bar, Bar]'.
!!! error TS2345: Type 'FooIterator' is missing the following properties from type '[Bar, Bar]': 0, 1, length, pop, and 26 more.
~~~~~~~~~~~~~~~~~~~
!!! error TS2449: Class 'FooIteratorIterator' used before its declaration.
!!! related TS2728 tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts:18:7: 'FooIteratorIterator' is declared here.

View file

@ -1,10 +1,8 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern26.ts(2,21): error TS2345: Argument of type 'Map<string, number>' is not assignable to parameter of type '[string, number]'.
Type 'Map<string, number>' is missing the following properties from type '[string, number]': 0, 1, length, pop, and 22 more.
==== tests/cases/conformance/es6/destructuring/iterableArrayPattern26.ts (1 errors) ====
function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]: [string, number][]) { }
takeFirstTwoEntries(new Map([["", 0], ["hello", 1]]));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'Map<string, number>' is not assignable to parameter of type '[string, number]'.
!!! error TS2345: Type 'Map<string, number>' is missing the following properties from type '[string, number]': 0, 1, length, pop, and 22 more.
!!! error TS2345: Argument of type 'Map<string, number>' is not assignable to parameter of type '[string, number]'.

View file

@ -2,11 +2,11 @@ tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(9,12): error TS13
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(10,15): error TS1354: 'readonly' type modifier is only permitted on array and tuple literal types.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(11,12): error TS1354: 'readonly' type modifier is only permitted on array and tuple literal types.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(12,12): error TS1354: 'readonly' type modifier is only permitted on array and tuple literal types.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(15,5): error TS2740: Type 'readonly string[]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(17,5): error TS2740: Type 'readonly [string, string]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(15,5): error TS4104: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(17,5): error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(21,5): error TS2739: Type 'string[]' is missing the following properties from type '[string, string]': 0, 1
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(22,5): error TS2740: Type 'readonly string[]' is missing the following properties from type '[string, string]': 0, 1, pop, push, and 5 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(23,5): error TS2740: Type 'readonly [string, string]' is missing the following properties from type '[string, string]': pop, push, reverse, shift, and 3 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(23,5): error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type '[string, string]'.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(24,5): error TS2739: Type 'string[]' is missing the following properties from type 'readonly [string, string]': 0, 1
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(25,5): error TS2739: Type 'readonly string[]' is missing the following properties from type 'readonly [string, string]': 0, 1
@ -36,11 +36,11 @@ tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(25,5): error TS27
function f1(ma: string[], ra: readonly string[], mt: [string, string], rt: readonly [string, string]) {
ma = ra; // Error
~~
!!! error TS2740: Type 'readonly string[]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
!!! error TS4104: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
ma = mt;
ma = rt; // Error
~~
!!! error TS2740: Type 'readonly [string, string]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
!!! error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
ra = ma;
ra = mt;
ra = rt;
@ -52,7 +52,7 @@ tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(25,5): error TS27
!!! error TS2740: Type 'readonly string[]' is missing the following properties from type '[string, string]': 0, 1, pop, push, and 5 more.
mt = rt; // Error
~~
!!! error TS2740: Type 'readonly [string, string]' is missing the following properties from type '[string, string]': pop, push, reverse, shift, and 3 more.
!!! error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type '[string, string]'.
rt = ma; // Error
~~
!!! error TS2739: Type 'string[]' is missing the following properties from type 'readonly [string, string]': 0, 1

View file

@ -0,0 +1,58 @@
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(10,20): error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type '[number, number]'.
The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type '[number, number]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(13,8): error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(16,9): error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(22,9): error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(23,9): error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(24,9): error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
==== tests/cases/compiler/readonlyTupleAndArrayElaboration.ts (6 errors) ====
// @strict
// #Repro from #30839
let point = [3, 4] as const;
function distanceFromOrigin([x, y]: [number, number]) {
return Math.sqrt(x ** 2 + y ** 2);
}
distanceFromOrigin(point);
~~~~~
!!! error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type '[number, number]'.
!!! error TS2345: The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type '[number, number]'.
declare function arryFn(x: number[]): void;
arryFn(point);
~~~~~
!!! error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
declare function arryFn2(x: Array<number>): void;
arryFn2(point);
~~~~~
!!! error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
declare const a: readonly number[];
declare const b: Readonly<number[]>;
declare const c: ReadonlyArray<number>;
arryFn2(a);
~
!!! error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
arryFn2(b);
~
!!! error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
arryFn2(c);
~
!!! error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

View file

@ -0,0 +1,41 @@
//// [readonlyTupleAndArrayElaboration.ts]
// @strict
// #Repro from #30839
let point = [3, 4] as const;
function distanceFromOrigin([x, y]: [number, number]) {
return Math.sqrt(x ** 2 + y ** 2);
}
distanceFromOrigin(point);
declare function arryFn(x: number[]): void;
arryFn(point);
declare function arryFn2(x: Array<number>): void;
arryFn2(point);
declare const a: readonly number[];
declare const b: Readonly<number[]>;
declare const c: ReadonlyArray<number>;
arryFn2(a);
arryFn2(b);
arryFn2(c);
//// [readonlyTupleAndArrayElaboration.js]
// @strict
// #Repro from #30839
var point = [3, 4];
function distanceFromOrigin(_a) {
var x = _a[0], y = _a[1];
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
distanceFromOrigin(point);
arryFn(point);
arryFn2(point);
arryFn2(a);
arryFn2(b);
arryFn2(c);

View file

@ -0,0 +1,64 @@
=== tests/cases/compiler/readonlyTupleAndArrayElaboration.ts ===
// @strict
// #Repro from #30839
let point = [3, 4] as const;
>point : Symbol(point, Decl(readonlyTupleAndArrayElaboration.ts, 3, 3))
function distanceFromOrigin([x, y]: [number, number]) {
>distanceFromOrigin : Symbol(distanceFromOrigin, Decl(readonlyTupleAndArrayElaboration.ts, 3, 28))
>x : Symbol(x, Decl(readonlyTupleAndArrayElaboration.ts, 5, 29))
>y : Symbol(y, Decl(readonlyTupleAndArrayElaboration.ts, 5, 31))
return Math.sqrt(x ** 2 + y ** 2);
>Math.sqrt : Symbol(Math.sqrt, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>sqrt : Symbol(Math.sqrt, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(readonlyTupleAndArrayElaboration.ts, 5, 29))
>y : Symbol(y, Decl(readonlyTupleAndArrayElaboration.ts, 5, 31))
}
distanceFromOrigin(point);
>distanceFromOrigin : Symbol(distanceFromOrigin, Decl(readonlyTupleAndArrayElaboration.ts, 3, 28))
>point : Symbol(point, Decl(readonlyTupleAndArrayElaboration.ts, 3, 3))
declare function arryFn(x: number[]): void;
>arryFn : Symbol(arryFn, Decl(readonlyTupleAndArrayElaboration.ts, 9, 26))
>x : Symbol(x, Decl(readonlyTupleAndArrayElaboration.ts, 11, 24))
arryFn(point);
>arryFn : Symbol(arryFn, Decl(readonlyTupleAndArrayElaboration.ts, 9, 26))
>point : Symbol(point, Decl(readonlyTupleAndArrayElaboration.ts, 3, 3))
declare function arryFn2(x: Array<number>): void;
>arryFn2 : Symbol(arryFn2, Decl(readonlyTupleAndArrayElaboration.ts, 12, 14))
>x : Symbol(x, Decl(readonlyTupleAndArrayElaboration.ts, 14, 25))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
arryFn2(point);
>arryFn2 : Symbol(arryFn2, Decl(readonlyTupleAndArrayElaboration.ts, 12, 14))
>point : Symbol(point, Decl(readonlyTupleAndArrayElaboration.ts, 3, 3))
declare const a: readonly number[];
>a : Symbol(a, Decl(readonlyTupleAndArrayElaboration.ts, 17, 13))
declare const b: Readonly<number[]>;
>b : Symbol(b, Decl(readonlyTupleAndArrayElaboration.ts, 18, 13))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
declare const c: ReadonlyArray<number>;
>c : Symbol(c, Decl(readonlyTupleAndArrayElaboration.ts, 19, 13))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
arryFn2(a);
>arryFn2 : Symbol(arryFn2, Decl(readonlyTupleAndArrayElaboration.ts, 12, 14))
>a : Symbol(a, Decl(readonlyTupleAndArrayElaboration.ts, 17, 13))
arryFn2(b);
>arryFn2 : Symbol(arryFn2, Decl(readonlyTupleAndArrayElaboration.ts, 12, 14))
>b : Symbol(b, Decl(readonlyTupleAndArrayElaboration.ts, 18, 13))
arryFn2(c);
>arryFn2 : Symbol(arryFn2, Decl(readonlyTupleAndArrayElaboration.ts, 12, 14))
>c : Symbol(c, Decl(readonlyTupleAndArrayElaboration.ts, 19, 13))

View file

@ -0,0 +1,77 @@
=== tests/cases/compiler/readonlyTupleAndArrayElaboration.ts ===
// @strict
// #Repro from #30839
let point = [3, 4] as const;
>point : readonly [3, 4]
>[3, 4] as const : readonly [3, 4]
>[3, 4] : readonly [3, 4]
>3 : 3
>4 : 4
function distanceFromOrigin([x, y]: [number, number]) {
>distanceFromOrigin : ([x, y]: [number, number]) => number
>x : number
>y : number
return Math.sqrt(x ** 2 + y ** 2);
>Math.sqrt(x ** 2 + y ** 2) : number
>Math.sqrt : (x: number) => number
>Math : Math
>sqrt : (x: number) => number
>x ** 2 + y ** 2 : number
>x ** 2 : number
>x : number
>2 : 2
>y ** 2 : number
>y : number
>2 : 2
}
distanceFromOrigin(point);
>distanceFromOrigin(point) : number
>distanceFromOrigin : ([x, y]: [number, number]) => number
>point : readonly [3, 4]
declare function arryFn(x: number[]): void;
>arryFn : (x: number[]) => void
>x : number[]
arryFn(point);
>arryFn(point) : void
>arryFn : (x: number[]) => void
>point : readonly [3, 4]
declare function arryFn2(x: Array<number>): void;
>arryFn2 : (x: number[]) => void
>x : number[]
arryFn2(point);
>arryFn2(point) : void
>arryFn2 : (x: number[]) => void
>point : readonly [3, 4]
declare const a: readonly number[];
>a : readonly number[]
declare const b: Readonly<number[]>;
>b : readonly number[]
declare const c: ReadonlyArray<number>;
>c : readonly number[]
arryFn2(a);
>arryFn2(a) : void
>arryFn2 : (x: number[]) => void
>a : readonly number[]
arryFn2(b);
>arryFn2(b) : void
>arryFn2 : (x: number[]) => void
>b : readonly number[]
arryFn2(c);
>arryFn2(c) : void
>arryFn2 : (x: number[]) => void
>c : readonly number[]

View file

@ -0,0 +1,24 @@
// @strict
// #Repro from #30839
let point = [3, 4] as const;
function distanceFromOrigin([x, y]: [number, number]) {
return Math.sqrt(x ** 2 + y ** 2);
}
distanceFromOrigin(point);
declare function arryFn(x: number[]): void;
arryFn(point);
declare function arryFn2(x: Array<number>): void;
arryFn2(point);
declare const a: readonly number[];
declare const b: Readonly<number[]>;
declare const c: ReadonlyArray<number>;
arryFn2(a);
arryFn2(b);
arryFn2(c);