Skip to content

Commit b6ae492

Browse files
authored
Add missing arity check on second inference pass (microsoft#29386)
1 parent 9bd2365 commit b6ae492

6 files changed

+106
-0
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20422,6 +20422,12 @@ namespace ts {
2042220422
if (inferenceContext) {
2042320423
const typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
2042420424
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration));
20425+
// If the original signature has a generic rest type, instantiation may produce a
20426+
// signature with different arity and we need to perform another arity check.
20427+
if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
20428+
candidateForArgumentArityError = checkCandidate;
20429+
continue;
20430+
}
2042520431
}
2042620432
if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) {
2042720433
// Give preference to error candidates that have no rest parameters (as they are more specific)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error TS2318: Cannot find global type 'IterableIterator'.
2+
tests/cases/compiler/spreadOfParamsFromGeneratorMakesRequiredParams.ts(6,1): error TS2554: Expected 2 arguments, but got 1.
3+
4+
5+
!!! error TS2318: Cannot find global type 'IterableIterator'.
6+
==== tests/cases/compiler/spreadOfParamsFromGeneratorMakesRequiredParams.ts (1 errors) ====
7+
declare function call<Fn extends (...args: any[]) => any>(
8+
fn: Fn,
9+
...args: Parameters<Fn>
10+
): any;
11+
12+
call(function* (a: 'a') { }); // error, 2nd argument required
13+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14+
!!! error TS2554: Expected 2 arguments, but got 1.
15+
!!! related TS6210 tests/cases/compiler/spreadOfParamsFromGeneratorMakesRequiredParams.ts:3:5: An argument for 'args' was not provided.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//// [spreadOfParamsFromGeneratorMakesRequiredParams.ts]
2+
declare function call<Fn extends (...args: any[]) => any>(
3+
fn: Fn,
4+
...args: Parameters<Fn>
5+
): any;
6+
7+
call(function* (a: 'a') { }); // error, 2nd argument required
8+
9+
//// [spreadOfParamsFromGeneratorMakesRequiredParams.js]
10+
var __generator = (this && this.__generator) || function (thisArg, body) {
11+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13+
function verb(n) { return function (v) { return step([n, v]); }; }
14+
function step(op) {
15+
if (f) throw new TypeError("Generator is already executing.");
16+
while (_) try {
17+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18+
if (y = 0, t) op = [op[0] & 2, t.value];
19+
switch (op[0]) {
20+
case 0: case 1: t = op; break;
21+
case 4: _.label++; return { value: op[1], done: false };
22+
case 5: _.label++; y = op[1]; op = [0]; continue;
23+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
24+
default:
25+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29+
if (t[2]) _.ops.pop();
30+
_.trys.pop(); continue;
31+
}
32+
op = body.call(thisArg, _);
33+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35+
}
36+
};
37+
call(function (a) { return __generator(this, function (_a) {
38+
return [2 /*return*/];
39+
}); }); // error, 2nd argument required
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/spreadOfParamsFromGeneratorMakesRequiredParams.ts ===
2+
declare function call<Fn extends (...args: any[]) => any>(
3+
>call : Symbol(call, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 0))
4+
>Fn : Symbol(Fn, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 22))
5+
>args : Symbol(args, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 34))
6+
7+
fn: Fn,
8+
>fn : Symbol(fn, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 58))
9+
>Fn : Symbol(Fn, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 22))
10+
11+
...args: Parameters<Fn>
12+
>args : Symbol(args, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 1, 11))
13+
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
14+
>Fn : Symbol(Fn, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 22))
15+
16+
): any;
17+
18+
call(function* (a: 'a') { }); // error, 2nd argument required
19+
>call : Symbol(call, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 0, 0))
20+
>a : Symbol(a, Decl(spreadOfParamsFromGeneratorMakesRequiredParams.ts, 5, 16))
21+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/spreadOfParamsFromGeneratorMakesRequiredParams.ts ===
2+
declare function call<Fn extends (...args: any[]) => any>(
3+
>call : <Fn extends (...args: any[]) => any>(fn: Fn, ...args: Parameters<Fn>) => any
4+
>args : any[]
5+
6+
fn: Fn,
7+
>fn : Fn
8+
9+
...args: Parameters<Fn>
10+
>args : Parameters<Fn>
11+
12+
): any;
13+
14+
call(function* (a: 'a') { }); // error, 2nd argument required
15+
>call(function* (a: 'a') { }) : any
16+
>call : <Fn extends (...args: any[]) => any>(fn: Fn, ...args: Parameters<Fn>) => any
17+
>function* (a: 'a') { } : (a: "a") => {}
18+
>a : "a"
19+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
declare function call<Fn extends (...args: any[]) => any>(
2+
fn: Fn,
3+
...args: Parameters<Fn>
4+
): any;
5+
6+
call(function* (a: 'a') { }); // error, 2nd argument required

0 commit comments

Comments
 (0)