From 0bf6c67b9b05484f83dfde14979cc584e1038223 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sat, 24 Aug 2019 19:56:19 +0900 Subject: [PATCH 1/2] fix error when use spread arguments twice --- src/compiler/checker.ts | 23 +++++++--- .../reference/callWithSpread3.errors.txt | 25 ++++++++--- tests/baselines/reference/callWithSpread3.js | 19 +++++++- .../reference/callWithSpread3.symbols | 33 ++++++++++++++ .../baselines/reference/callWithSpread3.types | 44 +++++++++++++++++++ .../functionCalls/callWithSpread3.ts | 12 ++++- 6 files changed, 142 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4ed83e41eb510..3ca4498ec38c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25063,10 +25063,18 @@ namespace ts { // If we are missing the close parenthesis, the call is incomplete. callIsIncomplete = node.arguments.end === node.end; - // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range. - const spreadArgIndex = getSpreadArgumentIndex(args); - if (spreadArgIndex >= 0) { - return spreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || spreadArgIndex < getParameterCount(signature)); + // If one or more spread arguments are present, check that they correspond to a rest parameter or at least that they are in the valid range. + const firstSpreadArgIndex = getSpreadArgumentIndex(args); + if (firstSpreadArgIndex >= 0) { + if (firstSpreadArgIndex === args.length - 1) { + return firstSpreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || firstSpreadArgIndex < getParameterCount(signature)); + } + + let totalCount = countSpreadArgumentLength(args[firstSpreadArgIndex]); + for (let i = firstSpreadArgIndex; i < args.length; i++) { + totalCount += isSpreadArgument(args[i]) ? countSpreadArgumentLength(args[i]) : 1; + } + return totalCount >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || totalCount < getParameterCount(signature)); } } @@ -25089,6 +25097,11 @@ 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 | 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. @@ -25544,7 +25557,7 @@ namespace ts { const spreadArgument = args[length - 1]; const type = flowLoopCount ? checkExpression(spreadArgument.expression) : checkExpressionCached(spreadArgument.expression); if (isTupleType(type)) { - const typeArguments = getTypeArguments(type); + const typeArguments = getTypeArguments(type); const restIndex = type.target.hasRestElement ? typeArguments.length - 1 : -1; const syntheticArgs = map(typeArguments, (t, i) => createSyntheticExpression(spreadArgument, t, /*isSpread*/ i === restIndex, type.target.labeledElementDeclarations?.[i])); return concatenate(args.slice(0, length - 1), syntheticArgs); diff --git a/tests/baselines/reference/callWithSpread3.errors.txt b/tests/baselines/reference/callWithSpread3.errors.txt index 6e45b5ea7979f..e5f722efe6aa6 100644 --- a/tests/baselines/reference/callWithSpread3.errors.txt +++ b/tests/baselines/reference/callWithSpread3.errors.txt @@ -1,16 +1,20 @@ -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(5,14): error TS2554: Expected 2 arguments, but got 3. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(6,19): error TS2554: Expected 2 arguments, but got 5. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(7,19): error TS2556: Expected 2 arguments, but got 4 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(8,19): error TS2556: Expected 2 arguments, but got 5 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(9,16): error TS2556: Expected 2 arguments, but got 1 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(10,9): error TS2554: Expected 2 arguments, but got 3. +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 (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[] + // error takeTwo('a', ...t2); // error on ...t2 ~~~~~ !!! error TS2554: Expected 2 arguments, but got 3. @@ -29,4 +33,11 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(10,9): erro !!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:1:37: An argument for 'b' was not provided. takeTwo(...t3); // error on ...t3 ~~~~~ -!!! error TS2554: Expected 2 arguments, but got 3. \ No newline at end of file +!!! error TS2554: Expected 2 arguments, but got 3. + + // ok + takeTwoOrMore(...t4); + takeTwoOrMore(...t4, ...t5); + takeTwoOrMore(...t4, ...t4); + takeTwoOrMore(...t5, ...t4); + \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread3.js b/tests/baselines/reference/callWithSpread3.js index bcb30625f46ce..040dd6ceed880 100644 --- a/tests/baselines/reference/callWithSpread3.js +++ b/tests/baselines/reference/callWithSpread3.js @@ -2,13 +2,24 @@ 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[] +// 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 +takeTwo(...t3); // error on ...t3 + +// ok +takeTwoOrMore(...t4); +takeTwoOrMore(...t4, ...t5); +takeTwoOrMore(...t4, ...t4); +takeTwoOrMore(...t5, ...t4); + //// [callWithSpread3.js] var __spreadArrays = (this && this.__spreadArrays) || function () { @@ -18,9 +29,15 @@ var __spreadArrays = (this && this.__spreadArrays) || function () { r[k] = a[j]; 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 +// 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)); diff --git a/tests/baselines/reference/callWithSpread3.symbols b/tests/baselines/reference/callWithSpread3.symbols index 3f0ea2d8dd814..b8a90f181d765 100644 --- a/tests/baselines/reference/callWithSpread3.symbols +++ b/tests/baselines/reference/callWithSpread3.symbols @@ -10,6 +10,19 @@ declare const t2: [string, string]; declare const t3: [string, string, string]; >t3 : Symbol(t3, 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 t4: [string, string, ...string[]] +>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13)) + +declare const t5: string[] +>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13)) + +// error takeTwo('a', ...t2); // error on ...t2 >takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) >t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) @@ -34,3 +47,23 @@ takeTwo(...t3); // error on ...t3 >takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) >t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13)) +// ok +takeTwoOrMore(...t4); +>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43)) +>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 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)) + +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)) + +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)) + diff --git a/tests/baselines/reference/callWithSpread3.types b/tests/baselines/reference/callWithSpread3.types index 5bbb0037774e8..8d6f8c1f38896 100644 --- a/tests/baselines/reference/callWithSpread3.types +++ b/tests/baselines/reference/callWithSpread3.types @@ -10,6 +10,19 @@ declare const 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 +>a : string +>b : string +>c : string[] + +declare const t4: [string, string, ...string[]] +>t4 : [string, string, ...string[]] + +declare const t5: string[] +>t5 : string[] + +// error takeTwo('a', ...t2); // error on ...t2 >takeTwo('a', ...t2) : void >takeTwo : (a: string, b: string) => void @@ -58,3 +71,34 @@ takeTwo(...t3); // error on ...t3 >...t3 : string >t3 : [string, string, string] +// ok +takeTwoOrMore(...t4); +>takeTwoOrMore(...t4) : void +>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void +>...t4 : string +>t4 : [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[] + +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[]] + +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[]] + diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts index bc5d8c2246fa8..bb9ae18382e10 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts @@ -1,10 +1,20 @@ 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[] +// 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 \ No newline at end of file +takeTwo(...t3); // error on ...t3 + +// ok +takeTwoOrMore(...t4); +takeTwoOrMore(...t4, ...t5); +takeTwoOrMore(...t4, ...t4); +takeTwoOrMore(...t5, ...t4); From f50515010e092af09b9c5995b79b58b272add31e Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Tue, 26 May 2020 19:54:11 -0400 Subject: [PATCH 2/2] 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.) --- src/compiler/checker.ts | 33 +-- .../reference/callWithSpread3.errors.txt | 92 ++++--- tests/baselines/reference/callWithSpread3.js | 77 ++++-- .../reference/callWithSpread3.symbols | 168 ++++++++----- .../baselines/reference/callWithSpread3.types | 225 ++++++++++++------ .../genericRestParameters1.errors.txt | 21 +- .../reference/genericRestParameters1.js | 8 +- .../reference/genericRestParameters1.symbols | 4 +- .../reference/genericRestParameters1.types | 4 +- .../functionCalls/callWithSpread3.ts | 47 ++-- .../types/rest/genericRestParameters1.ts | 4 +- 11 files changed, 450 insertions(+), 233 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3ca4498ec38c2..45b48bbcd880f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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(args[firstSpreadArgIndex]); + let totalCount = firstSpreadArgIndex; // count previous arguments for (let i = firstSpreadArgIndex; i < args.length; i++) { - totalCount += isSpreadArgument(args[i]) ? countSpreadArgumentLength(args[i]) : 1; + const arg = args[i]; + if (!isSpreadArgument(arg)) { + totalCount += 1; + } + else { + const argType = flowLoopCount ? checkExpression((arg).expression) : checkExpressionCached((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 | 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. diff --git a/tests/baselines/reference/callWithSpread3.errors.txt b/tests/baselines/reference/callWithSpread3.errors.txt index e5f722efe6aa6..71fc0334633f8 100644 --- a/tests/baselines/reference/callWithSpread3.errors.txt +++ b/tests/baselines/reference/callWithSpread3.errors.txt @@ -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); \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread3.js b/tests/baselines/reference/callWithSpread3.js index 040dd6ceed880..6100d0c2112ec 100644 --- a/tests/baselines/reference/callWithSpread3.js +++ b/tests/baselines/reference/callWithSpread3.js @@ -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)); diff --git a/tests/baselines/reference/callWithSpread3.symbols b/tests/baselines/reference/callWithSpread3.symbols index b8a90f181d765..e305b1d03ed6d 100644 --- a/tests/baselines/reference/callWithSpread3.symbols +++ b/tests/baselines/reference/callWithSpread3.symbols @@ -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)) -// error -takeTwo('a', ...t2); // error on ...t2 ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 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)) +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)) -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)) +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)) -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)) +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)) -takeTwo(...t2, 'a'); // error on 'a' ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +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)) -takeTwo(...t3); // error on ...t3 ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13)) +// error +fs2('a', ...s2); // error on ...s2 +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 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)) + +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)) + +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)) + +fs2(...s2, 'a'); // error on 'a' +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 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)) - -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)) - -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)) - -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_(...s2_); +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 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)) + +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)) + +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)) diff --git a/tests/baselines/reference/callWithSpread3.types b/tests/baselines/reference/callWithSpread3.types index 8d6f8c1f38896..dc7c7b4378772 100644 --- a/tests/baselines/reference/callWithSpread3.types +++ b/tests/baselines/reference/callWithSpread3.types @@ -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 ->a : string ->b : string +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 t2: [string, string]; ->t2 : [string, string] +declare const s2n_: [string, string, ...number[]]; +>s2n_ : [string, string, ...number[]] -declare const t3: [string, string, string]; ->t3 : [string, string, string] +declare function fs2(a: string, b: string): void; +>fs2 : (a: string, b: string) => void +>a : string +>b : 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[]] - -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[] - -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[]] - -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_(...s2_); +>fs2_(...s2_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s2_ : string +>s2_ : [string, string, ...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[] + +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[]] + +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] diff --git a/tests/baselines/reference/genericRestParameters1.errors.txt b/tests/baselines/reference/genericRestParameters1.errors.txt index cd9e799535bdb..707e86a94dd8f 100644 --- a/tests/baselines/reference/genericRestParameters1.errors.txt +++ b/tests/baselines/reference/genericRestParameters1.errors.txt @@ -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(...args: T): T; diff --git a/tests/baselines/reference/genericRestParameters1.js b/tests/baselines/reference/genericRestParameters1.js index eecb906462f30..0e094d0f288fd 100644 --- a/tests/baselines/reference/genericRestParameters1.js +++ b/tests/baselines/reference/genericRestParameters1.js @@ -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(...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] diff --git a/tests/baselines/reference/genericRestParameters1.symbols b/tests/baselines/reference/genericRestParameters1.symbols index 4b0dae5115006..56f1bc6cf5869 100644 --- a/tests/baselines/reference/genericRestParameters1.symbols +++ b/tests/baselines/reference/genericRestParameters1.symbols @@ -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)) diff --git a/tests/baselines/reference/genericRestParameters1.types b/tests/baselines/reference/genericRestParameters1.types index 1503f11845964..6dfee15241288 100644 --- a/tests/baselines/reference/genericRestParameters1.types +++ b/tests/baselines/reference/genericRestParameters1.types @@ -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 diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts index bb9ae18382e10..88f9af46df5a4 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts @@ -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); diff --git a/tests/cases/conformance/types/rest/genericRestParameters1.ts b/tests/cases/conformance/types/rest/genericRestParameters1.ts index 6572512cbfbe3..ede07b0d9ac58 100644 --- a/tests/cases/conformance/types/rest/genericRestParameters1.ts +++ b/tests/cases/conformance/types/rest/genericRestParameters1.ts @@ -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(...args: T): T;