Make hasCorrectArity handle tuples properly

This completes the work that started in PR #33069, and fixes #32835.

There are probably two additional related changes that are needed to
make this more complete:

* Fix the code that composes the error message (see the first two
  `FIXME`s in `callWithSpread3.ts`).

* Fix the code that checks the argument types (second two `FIXME`s).

* There is also an error in `genericRestParameters1.ts` which changed
  but should not be an error in the first place.  Added a `FIXME` there
  too.  (Probably will work if the previous iterm is done.)

In addition, `getEffectiveCallArguments` munges the arguments in case of
a spread in the last argument which might be better to avoid.  (I think
that there are cases where it wouldn't work anyway, such as a spread of
an array followed by a spread of an empty array.)
This commit is contained in:
Eli Barzilay
2020-06-04 23:46:56 -04:00
parent 261386d48b
commit 3151e2a365
11 changed files with 442 additions and 225 deletions
+19 -14
View File
@@ -25051,13 +25051,12 @@ namespace ts {
effectiveParameterCount = args.length === 0 ? effectiveParameterCount : 1; // class may have argumentless ctor functions - still resolve ctor and compare vs props member type
effectiveMinimumArguments = Math.min(effectiveMinimumArguments, 1); // sfc may specify context argument - handled by framework and not typechecked
}
else if (!node.arguments) {
// This only happens when we have something of the form: 'new C'
Debug.assert(node.kind === SyntaxKind.NewExpression);
return getMinArgumentCount(signature) === 0;
}
else {
if (!node.arguments) {
// This only happens when we have something of the form: 'new C'
Debug.assert(node.kind === SyntaxKind.NewExpression);
return getMinArgumentCount(signature) === 0;
}
argCount = signatureHelpTrailingComma ? args.length + 1 : args.length;
// If we are missing the close parenthesis, the call is incomplete.
@@ -25067,14 +25066,25 @@ namespace ts {
const firstSpreadArgIndex = getSpreadArgumentIndex(args);
if (firstSpreadArgIndex >= 0) {
if (firstSpreadArgIndex === args.length - 1) {
// Special case, handles the munged arguments that we receive in case of a spread in the end (breaks the arg.expression below)
// (see below for code that starts with "const spreadArgument")
return firstSpreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || firstSpreadArgIndex < getParameterCount(signature));
}
let totalCount = countSpreadArgumentLength(<SpreadElement>args[firstSpreadArgIndex]);
let totalCount = firstSpreadArgIndex; // count previous arguments
for (let i = firstSpreadArgIndex; i < args.length; i++) {
totalCount += isSpreadArgument(args[i]) ? countSpreadArgumentLength(<SpreadElement>args[i]) : 1;
const arg = args[i];
if (!isSpreadArgument(arg)) {
totalCount += 1;
}
else {
const argType = flowLoopCount ? checkExpression((<SpreadElement>arg).expression) : checkExpressionCached((<SpreadElement>arg).expression);
totalCount += isTupleType(argType) ? getTypeArguments(argType).length
: isArrayType(argType) ? 0
: 1;
}
}
return totalCount >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || totalCount < getParameterCount(signature));
return totalCount >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || totalCount <= getParameterCount(signature));
}
}
@@ -25097,11 +25107,6 @@ namespace ts {
return true;
}
function countSpreadArgumentLength(argment: SpreadElement): number {
const type = flowLoopCount ? checkExpression(argment.expression) : checkExpressionCached(argment.expression);
return isTupleType(type) ? getTypeArguments(type).length : 1;
}
function hasCorrectTypeArgumentArity(signature: Signature, typeArguments: NodeArray<TypeNode> | undefined) {
// If the user supplied type arguments, but the number of type arguments does not match
// the declared number of type parameters, the call has an incorrect arity.
@@ -1,43 +1,75 @@
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(9,14): error TS2554: Expected 2 arguments, but got 3.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(10,19): error TS2554: Expected 2 arguments, but got 5.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(11,19): error TS2556: Expected 2 arguments, but got 4 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(12,19): error TS2556: Expected 2 arguments, but got 5 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(13,16): error TS2556: Expected 2 arguments, but got 1 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(14,9): error TS2554: Expected 2 arguments, but got 3.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(14,10): error TS2554: Expected 2 arguments, but got 3.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(15,15): error TS2554: Expected 2 arguments, but got 5.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(16,15): error TS2556: Expected 2 arguments, but got 4 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(17,15): error TS2556: Expected 2 arguments, but got 5 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(18,12): error TS2556: Expected 2 arguments, but got 1 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(19,5): error TS2554: Expected 2 arguments, but got 3.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(20,6): error TS2557: Expected at least 2 arguments, but got 0 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(21,6): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(22,13): error TS2557: Expected at least 2 arguments, but got 1 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(23,13): error TS2557: Expected at least 2 arguments, but got 2 or more.
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(25,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
==== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts (6 errors) ====
declare function takeTwo(a: string, b: string): void;
declare const t2: [string, string];
declare const t3: [string, string, string];
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
declare const t4: [string, string, ...string[]]
declare const t5: string[]
==== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts (11 errors) ====
declare const s2: [string, string];
declare const s3: [string, string, string];
declare const s2_: [string, string, ...string[]];
declare const s_: string[];
declare const n_: number[];
declare const s2n_: [string, string, ...number[]];
declare function fs2(a: string, b: string): void;
declare function fs2_(a: string, b: string, ...c: string[]): void;
declare function fs2n_(a: string, b: string, ...c: number[]): void;
declare function fs5(a: string, b: string, c: string, d: string, e: string): void;
// error
takeTwo('a', ...t2); // error on ...t2
~~~~~
fs2('a', ...s2); // error on ...s2
~~~~~
!!! error TS2554: Expected 2 arguments, but got 3.
takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2
~~~~~~~~~~
fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2
~~~~~~~~~~
!!! error TS2554: Expected 2 arguments, but got 5.
takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c'
~~~~~~~~~~
fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c'
~~~~~~~~~~
!!! error TS2556: Expected 2 arguments, but got 4 or more.
takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd'
~~~~~~~~~~~~~~~
fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd'
~~~~~~~~~~~~~~~
!!! error TS2556: Expected 2 arguments, but got 5 or more.
takeTwo(...t2, 'a'); // error on 'a'
~~~
fs2(...s2, 'a'); // error on 'a'
~~~
!!! error TS2556: Expected 2 arguments, but got 1 or more.
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:1:37: An argument for 'b' was not provided.
takeTwo(...t3); // error on ...t3
~~~~~
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:8:33: An argument for 'b' was not provided.
fs2(...s3); // error on ...s3
~~~~~
!!! error TS2554: Expected 2 arguments, but got 3.
fs2_(...s_); // error on ...s_
~~~~~
!!! error TS2557: Expected at least 2 arguments, but got 0 or more.
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:9:23: An argument for 'a' was not provided.
fs2_(...s2n_); // error on ...s2n_
~~~~~~~
!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
fs2_(...s_, ...s_); // error FIXME: bad error message
~~~~~
!!! error TS2557: Expected at least 2 arguments, but got 1 or more.
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:9:34: An argument for 'b' was not provided.
fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message
~~~~~~~~~~~~
!!! error TS2557: Expected at least 2 arguments, but got 2 or more.
// fs2n_(...s2, ...s_); // FIXME: should be a type error
fs2n_(...s2_); // error on ...s2_
~~~~~~
!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
// ok
takeTwoOrMore(...t4);
takeTwoOrMore(...t4, ...t5);
takeTwoOrMore(...t4, ...t4);
takeTwoOrMore(...t5, ...t4);
fs2_(...s2_);
fs2_(...s2_, ...s_);
fs2_(...s2_, ...s2_);
fs2_(...s_, ...s2_);
fs2n_(...s2n_);
fs2n_(...s2);
// fs2n_(...s2, ...n_); // FIXME: should compile
fs5(...s2, "foo", ...s2);
+51 -26
View File
@@ -1,24 +1,39 @@
//// [callWithSpread3.ts]
declare function takeTwo(a: string, b: string): void;
declare const t2: [string, string];
declare const t3: [string, string, string];
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
declare const t4: [string, string, ...string[]]
declare const t5: string[]
declare const s2: [string, string];
declare const s3: [string, string, string];
declare const s2_: [string, string, ...string[]];
declare const s_: string[];
declare const n_: number[];
declare const s2n_: [string, string, ...number[]];
declare function fs2(a: string, b: string): void;
declare function fs2_(a: string, b: string, ...c: string[]): void;
declare function fs2n_(a: string, b: string, ...c: number[]): void;
declare function fs5(a: string, b: string, c: string, d: string, e: string): void;
// error
takeTwo('a', ...t2); // error on ...t2
takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2
takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c'
takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd'
takeTwo(...t2, 'a'); // error on 'a'
takeTwo(...t3); // error on ...t3
fs2('a', ...s2); // error on ...s2
fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2
fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c'
fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd'
fs2(...s2, 'a'); // error on 'a'
fs2(...s3); // error on ...s3
fs2_(...s_); // error on ...s_
fs2_(...s2n_); // error on ...s2n_
fs2_(...s_, ...s_); // error FIXME: bad error message
fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message
// fs2n_(...s2, ...s_); // FIXME: should be a type error
fs2n_(...s2_); // error on ...s2_
// ok
takeTwoOrMore(...t4);
takeTwoOrMore(...t4, ...t5);
takeTwoOrMore(...t4, ...t4);
takeTwoOrMore(...t5, ...t4);
fs2_(...s2_);
fs2_(...s2_, ...s_);
fs2_(...s2_, ...s2_);
fs2_(...s_, ...s2_);
fs2n_(...s2n_);
fs2n_(...s2);
// fs2n_(...s2, ...n_); // FIXME: should compile
fs5(...s2, "foo", ...s2);
//// [callWithSpread3.js]
@@ -30,14 +45,24 @@ var __spreadArrays = (this && this.__spreadArrays) || function () {
return r;
};
// error
takeTwo.apply(void 0, __spreadArrays(['a'], t2)); // error on ...t2
takeTwo.apply(void 0, __spreadArrays(['a', 'b', 'c'], t2)); // error on 'c' and ...t2
takeTwo.apply(void 0, __spreadArrays(['a', 'b'], t2, ['c'])); // error on ...t2 and 'c'
takeTwo.apply(void 0, __spreadArrays(['a', 'b', 'c'], t2, ['d'])); // error on 'c', ...t2 and 'd'
takeTwo.apply(void 0, __spreadArrays(t2, ['a'])); // error on 'a'
takeTwo.apply(void 0, t3); // error on ...t3
fs2.apply(void 0, __spreadArrays(['a'], s2)); // error on ...s2
fs2.apply(void 0, __spreadArrays(['a', 'b', 'c'], s2)); // error on 'c' and ...s2
fs2.apply(void 0, __spreadArrays(['a', 'b'], s2, ['c'])); // error on ...s2 and 'c'
fs2.apply(void 0, __spreadArrays(['a', 'b', 'c'], s2, ['d'])); // error on 'c', ...s2 and 'd'
fs2.apply(void 0, __spreadArrays(s2, ['a'])); // error on 'a'
fs2.apply(void 0, s3); // error on ...s3
fs2_.apply(void 0, s_); // error on ...s_
fs2_.apply(void 0, s2n_); // error on ...s2n_
fs2_.apply(void 0, __spreadArrays(s_, s_)); // error FIXME: bad error message
fs2_.apply(void 0, __spreadArrays(s_, s_, s_)); // error FIXME: worse error message
// fs2n_(...s2, ...s_); // FIXME: should be a type error
fs2n_.apply(void 0, s2_); // error on ...s2_
// ok
takeTwoOrMore.apply(void 0, t4);
takeTwoOrMore.apply(void 0, __spreadArrays(t4, t5));
takeTwoOrMore.apply(void 0, __spreadArrays(t4, t4));
takeTwoOrMore.apply(void 0, __spreadArrays(t5, t4));
fs2_.apply(void 0, s2_);
fs2_.apply(void 0, __spreadArrays(s2_, s_));
fs2_.apply(void 0, __spreadArrays(s2_, s2_));
fs2_.apply(void 0, __spreadArrays(s_, s2_));
fs2n_.apply(void 0, s2n_);
fs2n_.apply(void 0, s2);
// fs2n_(...s2, ...n_); // FIXME: should compile
fs5.apply(void 0, __spreadArrays(s2, ["foo"], s2));
+108 -50
View File
@@ -1,69 +1,127 @@
=== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts ===
declare function takeTwo(a: string, b: string): void;
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>a : Symbol(a, Decl(callWithSpread3.ts, 0, 25))
>b : Symbol(b, Decl(callWithSpread3.ts, 0, 35))
declare const s2: [string, string];
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
declare const t2: [string, string];
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
declare const s3: [string, string, string];
>s3 : Symbol(s3, Decl(callWithSpread3.ts, 1, 13))
declare const t3: [string, string, string];
>t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13))
declare const s2_: [string, string, ...string[]];
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
>a : Symbol(a, Decl(callWithSpread3.ts, 3, 32))
>b : Symbol(b, Decl(callWithSpread3.ts, 3, 42))
>c : Symbol(c, Decl(callWithSpread3.ts, 3, 53))
declare const s_: string[];
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
declare const t4: [string, string, ...string[]]
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
declare const n_: number[];
>n_ : Symbol(n_, Decl(callWithSpread3.ts, 4, 13))
declare const t5: string[]
>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13))
declare const s2n_: [string, string, ...number[]];
>s2n_ : Symbol(s2n_, Decl(callWithSpread3.ts, 5, 13))
declare function fs2(a: string, b: string): void;
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>a : Symbol(a, Decl(callWithSpread3.ts, 7, 21))
>b : Symbol(b, Decl(callWithSpread3.ts, 7, 31))
declare function fs2_(a: string, b: string, ...c: string[]): void;
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>a : Symbol(a, Decl(callWithSpread3.ts, 8, 22))
>b : Symbol(b, Decl(callWithSpread3.ts, 8, 32))
>c : Symbol(c, Decl(callWithSpread3.ts, 8, 43))
declare function fs2n_(a: string, b: string, ...c: number[]): void;
>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66))
>a : Symbol(a, Decl(callWithSpread3.ts, 9, 23))
>b : Symbol(b, Decl(callWithSpread3.ts, 9, 33))
>c : Symbol(c, Decl(callWithSpread3.ts, 9, 44))
declare function fs5(a: string, b: string, c: string, d: string, e: string): void;
>fs5 : Symbol(fs5, Decl(callWithSpread3.ts, 9, 67))
>a : Symbol(a, Decl(callWithSpread3.ts, 10, 21))
>b : Symbol(b, Decl(callWithSpread3.ts, 10, 31))
>c : Symbol(c, Decl(callWithSpread3.ts, 10, 42))
>d : Symbol(d, Decl(callWithSpread3.ts, 10, 53))
>e : Symbol(e, Decl(callWithSpread3.ts, 10, 64))
// error
takeTwo('a', ...t2); // error on ...t2
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
fs2('a', ...s2); // error on ...s2
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c'
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c'
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd'
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd'
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
takeTwo(...t2, 'a'); // error on 'a'
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
fs2(...s2, 'a'); // error on 'a'
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
takeTwo(...t3); // error on ...t3
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
>t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13))
fs2(...s3); // error on ...s3
>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50))
>s3 : Symbol(s3, Decl(callWithSpread3.ts, 1, 13))
fs2_(...s_); // error on ...s_
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
fs2_(...s2n_); // error on ...s2n_
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s2n_ : Symbol(s2n_, Decl(callWithSpread3.ts, 5, 13))
fs2_(...s_, ...s_); // error FIXME: bad error message
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
// fs2n_(...s2, ...s_); // FIXME: should be a type error
fs2n_(...s2_); // error on ...s2_
>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66))
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
// ok
takeTwoOrMore(...t4);
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
fs2_(...s2_);
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
takeTwoOrMore(...t4, ...t5);
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13))
fs2_(...s2_, ...s_);
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
takeTwoOrMore(...t4, ...t4);
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
fs2_(...s2_, ...s2_);
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
takeTwoOrMore(...t5, ...t4);
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13))
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
fs2_(...s_, ...s2_);
>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49))
>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13))
>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13))
fs2n_(...s2n_);
>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66))
>s2n_ : Symbol(s2n_, Decl(callWithSpread3.ts, 5, 13))
fs2n_(...s2);
>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
// fs2n_(...s2, ...n_); // FIXME: should compile
fs5(...s2, "foo", ...s2);
>fs5 : Symbol(fs5, Decl(callWithSpread3.ts, 9, 67))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13))
+149 -70
View File
@@ -1,104 +1,183 @@
=== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts ===
declare function takeTwo(a: string, b: string): void;
>takeTwo : (a: string, b: string) => void
declare const s2: [string, string];
>s2 : [string, string]
declare const s3: [string, string, string];
>s3 : [string, string, string]
declare const s2_: [string, string, ...string[]];
>s2_ : [string, string, ...string[]]
declare const s_: string[];
>s_ : string[]
declare const n_: number[];
>n_ : number[]
declare const s2n_: [string, string, ...number[]];
>s2n_ : [string, string, ...number[]]
declare function fs2(a: string, b: string): void;
>fs2 : (a: string, b: string) => void
>a : string
>b : string
declare const t2: [string, string];
>t2 : [string, string]
declare const t3: [string, string, string];
>t3 : [string, string, string]
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
declare function fs2_(a: string, b: string, ...c: string[]): void;
>fs2_ : (a: string, b: string, ...c: string[]) => void
>a : string
>b : string
>c : string[]
declare const t4: [string, string, ...string[]]
>t4 : [string, string, ...string[]]
declare function fs2n_(a: string, b: string, ...c: number[]): void;
>fs2n_ : (a: string, b: string, ...c: number[]) => void
>a : string
>b : string
>c : number[]
declare const t5: string[]
>t5 : string[]
declare function fs5(a: string, b: string, c: string, d: string, e: string): void;
>fs5 : (a: string, b: string, c: string, d: string, e: string) => void
>a : string
>b : string
>c : string
>d : string
>e : string
// error
takeTwo('a', ...t2); // error on ...t2
>takeTwo('a', ...t2) : void
>takeTwo : (a: string, b: string) => void
fs2('a', ...s2); // error on ...s2
>fs2('a', ...s2) : void
>fs2 : (a: string, b: string) => void
>'a' : "a"
>...t2 : string
>t2 : [string, string]
>...s2 : string
>s2 : [string, string]
takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2
>takeTwo('a', 'b', 'c', ...t2) : void
>takeTwo : (a: string, b: string) => void
fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2
>fs2('a', 'b', 'c', ...s2) : void
>fs2 : (a: string, b: string) => void
>'a' : "a"
>'b' : "b"
>'c' : "c"
>...t2 : string
>t2 : [string, string]
>...s2 : string
>s2 : [string, string]
takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c'
>takeTwo('a', 'b', ...t2, 'c') : void
>takeTwo : (a: string, b: string) => void
fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c'
>fs2('a', 'b', ...s2, 'c') : void
>fs2 : (a: string, b: string) => void
>'a' : "a"
>'b' : "b"
>...t2 : string
>t2 : [string, string]
>...s2 : string
>s2 : [string, string]
>'c' : "c"
takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd'
>takeTwo('a', 'b', 'c', ...t2, 'd') : void
>takeTwo : (a: string, b: string) => void
fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd'
>fs2('a', 'b', 'c', ...s2, 'd') : void
>fs2 : (a: string, b: string) => void
>'a' : "a"
>'b' : "b"
>'c' : "c"
>...t2 : string
>t2 : [string, string]
>...s2 : string
>s2 : [string, string]
>'d' : "d"
takeTwo(...t2, 'a'); // error on 'a'
>takeTwo(...t2, 'a') : void
>takeTwo : (a: string, b: string) => void
>...t2 : string
>t2 : [string, string]
fs2(...s2, 'a'); // error on 'a'
>fs2(...s2, 'a') : void
>fs2 : (a: string, b: string) => void
>...s2 : string
>s2 : [string, string]
>'a' : "a"
takeTwo(...t3); // error on ...t3
>takeTwo(...t3) : void
>takeTwo : (a: string, b: string) => void
>...t3 : string
>t3 : [string, string, string]
fs2(...s3); // error on ...s3
>fs2(...s3) : void
>fs2 : (a: string, b: string) => void
>...s3 : string
>s3 : [string, string, string]
fs2_(...s_); // error on ...s_
>fs2_(...s_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s_ : string
>s_ : string[]
fs2_(...s2n_); // error on ...s2n_
>fs2_(...s2n_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s2n_ : string | number
>s2n_ : [string, string, ...number[]]
fs2_(...s_, ...s_); // error FIXME: bad error message
>fs2_(...s_, ...s_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s_ : string
>s_ : string[]
>...s_ : string
>s_ : string[]
fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message
>fs2_(...s_, ...s_, ...s_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s_ : string
>s_ : string[]
>...s_ : string
>s_ : string[]
>...s_ : string
>s_ : string[]
// fs2n_(...s2, ...s_); // FIXME: should be a type error
fs2n_(...s2_); // error on ...s2_
>fs2n_(...s2_) : void
>fs2n_ : (a: string, b: string, ...c: number[]) => void
>...s2_ : string
>s2_ : [string, string, ...string[]]
// ok
takeTwoOrMore(...t4);
>takeTwoOrMore(...t4) : void
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
>...t4 : string
>t4 : [string, string, ...string[]]
fs2_(...s2_);
>fs2_(...s2_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s2_ : string
>s2_ : [string, string, ...string[]]
takeTwoOrMore(...t4, ...t5);
>takeTwoOrMore(...t4, ...t5) : void
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
>...t4 : string
>t4 : [string, string, ...string[]]
>...t5 : string
>t5 : string[]
fs2_(...s2_, ...s_);
>fs2_(...s2_, ...s_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s2_ : string
>s2_ : [string, string, ...string[]]
>...s_ : string
>s_ : string[]
takeTwoOrMore(...t4, ...t4);
>takeTwoOrMore(...t4, ...t4) : void
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
>...t4 : string
>t4 : [string, string, ...string[]]
>...t4 : string
>t4 : [string, string, ...string[]]
fs2_(...s2_, ...s2_);
>fs2_(...s2_, ...s2_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s2_ : string
>s2_ : [string, string, ...string[]]
>...s2_ : string
>s2_ : [string, string, ...string[]]
takeTwoOrMore(...t5, ...t4);
>takeTwoOrMore(...t5, ...t4) : void
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
>...t5 : string
>t5 : string[]
>...t4 : string
>t4 : [string, string, ...string[]]
fs2_(...s_, ...s2_);
>fs2_(...s_, ...s2_) : void
>fs2_ : (a: string, b: string, ...c: string[]) => void
>...s_ : string
>s_ : string[]
>...s2_ : string
>s2_ : [string, string, ...string[]]
fs2n_(...s2n_);
>fs2n_(...s2n_) : void
>fs2n_ : (a: string, b: string, ...c: number[]) => void
>...s2n_ : string | number
>s2n_ : [string, string, ...number[]]
fs2n_(...s2);
>fs2n_(...s2) : void
>fs2n_ : (a: string, b: string, ...c: number[]) => void
>...s2 : string
>s2 : [string, string]
// fs2n_(...s2, ...n_); // FIXME: should compile
fs5(...s2, "foo", ...s2);
>fs5(...s2, "foo", ...s2) : void
>fs5 : (a: string, b: string, c: string, d: string, e: string) => void
>...s2 : string
>s2 : [string, string]
>"foo" : "foo"
>...s2 : string
>s2 : [string, string]
@@ -1,5 +1,7 @@
tests/cases/conformance/types/rest/genericRestParameters1.ts(22,11): error TS2556: Expected 3 arguments, but got 1 or more.
tests/cases/conformance/types/rest/genericRestParameters1.ts(31,11): error TS2556: Expected 3 arguments, but got 1 or more.
tests/cases/conformance/types/rest/genericRestParameters1.ts(22,4): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/rest/genericRestParameters1.ts(31,4): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/rest/genericRestParameters1.ts(135,23): error TS2344: Type 'Function' does not satisfy the constraint '(...args: any) => any'.
Type 'Function' provides no match for the signature '(...args: any): any'.
tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS2322: Type '(a: never) => void' is not assignable to type '(...args: any[]) => void'.
@@ -29,9 +31,10 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232
f1(42, "hello", ...t1);
f1(42, "hello", true, ...t0);
f1(ns[0], ns[1], true);
f1(...ns, true); // Error, tuple spread only expanded when last
~~~~
!!! error TS2556: Expected 3 arguments, but got 1 or more.
f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
~~~~~
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'string' is not assignable to type 'number'.
f2(42, "hello", true);
f2(t3[0], t3[1], t3[2]);
@@ -40,10 +43,10 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232
f2(42, "hello", ...t1);
f2(42, "hello", true, ...t0);
f2(ns[0], ns[1], true);
f2(...ns, true); // Error, tuple spread only expanded when last
~~~~
!!! error TS2556: Expected 3 arguments, but got 1 or more.
!!! related TS6210 tests/cases/conformance/types/rest/genericRestParameters1.ts:2:30: An argument for 'x1' was not provided.
f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
~~~~~
!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'string' is not assignable to type 'number'.
declare function f10<T extends unknown[]>(...args: T): T;
@@ -20,7 +20,7 @@ f1(42, ...t2);
f1(42, "hello", ...t1);
f1(42, "hello", true, ...t0);
f1(ns[0], ns[1], true);
f1(...ns, true); // Error, tuple spread only expanded when last
f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
f2(42, "hello", true);
f2(t3[0], t3[1], t3[2]);
@@ -29,7 +29,7 @@ f2(42, ...t2);
f2(42, "hello", ...t1);
f2(42, "hello", true, ...t0);
f2(ns[0], ns[1], true);
f2(...ns, true); // Error, tuple spread only expanded when last
f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
declare function f10<T extends unknown[]>(...args: T): T;
@@ -183,7 +183,7 @@ f1.apply(void 0, __spreadArrays([42], t2));
f1.apply(void 0, __spreadArrays([42, "hello"], t1));
f1.apply(void 0, __spreadArrays([42, "hello", true], t0));
f1(ns[0], ns[1], true);
f1.apply(void 0, __spreadArrays(ns, [true])); // Error, tuple spread only expanded when last
f1.apply(void 0, __spreadArrays(ns, [true])); // FIXME: Error, since ...ns is considered as string|number here
f2(42, "hello", true);
f2(t3[0], t3[1], t3[2]);
f2.apply(void 0, t3);
@@ -191,7 +191,7 @@ f2.apply(void 0, __spreadArrays([42], t2));
f2.apply(void 0, __spreadArrays([42, "hello"], t1));
f2.apply(void 0, __spreadArrays([42, "hello", true], t0));
f2(ns[0], ns[1], true);
f2.apply(void 0, __spreadArrays(ns, [true])); // Error, tuple spread only expanded when last
f2.apply(void 0, __spreadArrays(ns, [true])); // FIXME: Error, since ...ns is considered as string|number here
var x10 = f10(42, "hello", true); // [number, string, boolean]
var x11 = f10(42, "hello"); // [number, string]
var x12 = f10(42); // [number]
@@ -70,7 +70,7 @@ f1(ns[0], ns[1], true);
>ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13))
>1 : Symbol(1)
f1(...ns, true); // Error, tuple spread only expanded when last
f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
>f1 : Symbol(f1, Decl(genericRestParameters1.ts, 0, 11))
>ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13))
@@ -109,7 +109,7 @@ f2(ns[0], ns[1], true);
>ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13))
>1 : Symbol(1)
f2(...ns, true); // Error, tuple spread only expanded when last
f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
>f2 : Symbol(f2, Decl(genericRestParameters1.ts, 1, 11))
>ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13))
@@ -98,7 +98,7 @@ f1(ns[0], ns[1], true);
>1 : 1
>true : true
f1(...ns, true); // Error, tuple spread only expanded when last
f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
>f1(...ns, true) : void
>f1 : (x_0: number, x_1: string, x_2: boolean) => void
>...ns : string | number
@@ -166,7 +166,7 @@ f2(ns[0], ns[1], true);
>1 : 1
>true : true
f2(...ns, true); // Error, tuple spread only expanded when last
f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
>f2(...ns, true) : void
>f2 : (x0: number, x1: string, x2: boolean) => void
>...ns : string | number
@@ -1,20 +1,35 @@
declare function takeTwo(a: string, b: string): void;
declare const t2: [string, string];
declare const t3: [string, string, string];
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
declare const t4: [string, string, ...string[]]
declare const t5: string[]
declare const s2: [string, string];
declare const s3: [string, string, string];
declare const s2_: [string, string, ...string[]];
declare const s_: string[];
declare const n_: number[];
declare const s2n_: [string, string, ...number[]];
declare function fs2(a: string, b: string): void;
declare function fs2_(a: string, b: string, ...c: string[]): void;
declare function fs2n_(a: string, b: string, ...c: number[]): void;
declare function fs5(a: string, b: string, c: string, d: string, e: string): void;
// error
takeTwo('a', ...t2); // error on ...t2
takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2
takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c'
takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd'
takeTwo(...t2, 'a'); // error on 'a'
takeTwo(...t3); // error on ...t3
fs2('a', ...s2); // error on ...s2
fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2
fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c'
fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd'
fs2(...s2, 'a'); // error on 'a'
fs2(...s3); // error on ...s3
fs2_(...s_); // error on ...s_
fs2_(...s2n_); // error on ...s2n_
fs2_(...s_, ...s_); // error FIXME: bad error message
fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message
// fs2n_(...s2, ...s_); // FIXME: should be a type error
fs2n_(...s2_); // error on ...s2_
// ok
takeTwoOrMore(...t4);
takeTwoOrMore(...t4, ...t5);
takeTwoOrMore(...t4, ...t4);
takeTwoOrMore(...t5, ...t4);
fs2_(...s2_);
fs2_(...s2_, ...s_);
fs2_(...s2_, ...s2_);
fs2_(...s_, ...s2_);
fs2n_(...s2n_);
fs2n_(...s2);
// fs2n_(...s2, ...n_); // FIXME: should compile
fs5(...s2, "foo", ...s2);
@@ -22,7 +22,7 @@ f1(42, ...t2);
f1(42, "hello", ...t1);
f1(42, "hello", true, ...t0);
f1(ns[0], ns[1], true);
f1(...ns, true); // Error, tuple spread only expanded when last
f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
f2(42, "hello", true);
f2(t3[0], t3[1], t3[2]);
@@ -31,7 +31,7 @@ f2(42, ...t2);
f2(42, "hello", ...t1);
f2(42, "hello", true, ...t0);
f2(ns[0], ns[1], true);
f2(...ns, true); // Error, tuple spread only expanded when last
f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here
declare function f10<T extends unknown[]>(...args: T): T;