Skip to content

Commit 5f2efc2

Browse files
committed
Properly handle all generic kinds of types in rest positions
1 parent feca91c commit 5f2efc2

File tree

1 file changed

+22
-22
lines changed

1 file changed

+22
-22
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10497,9 +10497,9 @@ namespace ts {
1049710497
}
1049810498

1049910499
const sourceCount = getParameterCount(source);
10500-
const sourceRestTypeParameter = getRestTypeParameter(source);
10501-
const targetRestTypeParameter = sourceRestTypeParameter ? getRestTypeParameter(target) : undefined;
10502-
if (sourceRestTypeParameter && !(targetRestTypeParameter && sourceCount === targetCount)) {
10500+
const sourceGenericRestType = getGenericRestType(source);
10501+
const targetGenericRestType = sourceGenericRestType ? getGenericRestType(target) : undefined;
10502+
if (sourceGenericRestType && !(targetGenericRestType && sourceCount === targetCount)) {
1050310503
return Ternary.False;
1050410504
}
1050510505

@@ -10528,8 +10528,8 @@ namespace ts {
1052810528
const paramCount = Math.max(sourceCount, targetCount);
1052910529
const lastIndex = paramCount - 1;
1053010530
for (let i = 0; i < paramCount; i++) {
10531-
const sourceType = i === lastIndex && sourceRestTypeParameter || getTypeAtPosition(source, i);
10532-
const targetType = i === lastIndex && targetRestTypeParameter || getTypeAtPosition(target, i);
10531+
const sourceType = i === lastIndex && sourceGenericRestType || getTypeAtPosition(source, i);
10532+
const targetType = i === lastIndex && targetGenericRestType || getTypeAtPosition(target, i);
1053310533
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
1053410534
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
1053510535
// they naturally relate only contra-variantly). However, if the source and target parameters both have
@@ -12804,13 +12804,13 @@ namespace ts {
1280412804
sourceHasRest ? targetCount :
1280512805
targetHasRest ? sourceCount :
1280612806
Math.min(sourceCount, targetCount);
12807-
const targetRestTypeVariable = getRestTypeParameter(target);
12808-
const paramCount = targetRestTypeVariable ? Math.min(targetCount - 1, maxCount) : maxCount;
12807+
const targetGenericRestType = getGenericRestType(target);
12808+
const paramCount = targetGenericRestType ? Math.min(targetCount - 1, maxCount) : maxCount;
1280912809
for (let i = 0; i < paramCount; i++) {
1281012810
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
1281112811
}
12812-
if (targetRestTypeVariable) {
12813-
callback(getRestTypeAtPosition(source, paramCount), targetRestTypeVariable);
12812+
if (targetGenericRestType) {
12813+
callback(getRestTypeAtPosition(source, paramCount), targetGenericRestType);
1281412814
}
1281512815
}
1281612816

@@ -18380,8 +18380,8 @@ namespace ts {
1838018380
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
1838118381
// wildcards for all context sensitive function expressions.
1838218382
const effectiveArgCount = getEffectiveArgumentCount(node, args, signature);
18383-
const restTypeParameter = getRestTypeParameter(signature);
18384-
const argCount = restTypeParameter ? Math.min(getParameterCount(signature) - 1, effectiveArgCount) : effectiveArgCount;
18383+
const genericRestType = getGenericRestType(signature);
18384+
const argCount = genericRestType ? Math.min(getParameterCount(signature) - 1, effectiveArgCount) : effectiveArgCount;
1838518385
for (let i = 0; i < argCount; i++) {
1838618386
const arg = getEffectiveArgument(node, args, i);
1838718387
// If the effective argument is 'undefined', then it is an argument that is present but is synthetic.
@@ -18400,9 +18400,9 @@ namespace ts {
1840018400
}
1840118401
}
1840218402

18403-
if (restTypeParameter) {
18404-
const spreadType = getSpreadArgumentType(node, args, argCount, effectiveArgCount, restTypeParameter, context);
18405-
inferTypes(context.inferences, spreadType, restTypeParameter);
18403+
if (genericRestType) {
18404+
const spreadType = getSpreadArgumentType(node, args, argCount, effectiveArgCount, genericRestType, context);
18405+
inferTypes(context.inferences, spreadType, genericRestType);
1840618406
}
1840718407

1840818408
// In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this
@@ -19152,9 +19152,9 @@ namespace ts {
1915219152
}
1915319153
const isJavascript = isInJavaScriptFile(candidate.declaration);
1915419154
candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript);
19155-
// If the original signature has a rest type parameter, instantiation may produce a
19155+
// If the original signature has a generic rest type, instantiation may produce a
1915619156
// signature with different arity and we need to perform another arity check.
19157-
if (getRestTypeParameter(originalCandidate) && !hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
19157+
if (getGenericRestType(originalCandidate) && !hasCorrectArity(node, args!, candidate, signatureHelpTrailingComma)) {
1915819158
candidateForArgumentArityError = candidate;
1915919159
break;
1916019160
}
@@ -20084,9 +20084,9 @@ namespace ts {
2008420084
const paramCount = getParameterCount(source);
2008520085
const hasRest = hasEffectiveRestParameter(source);
2008620086
if (hasRest && pos === paramCount - 1) {
20087-
const restTypeVariable = getRestTypeParameter(source);
20088-
if (restTypeVariable) {
20089-
return restTypeVariable;
20087+
const genericRestType = getGenericRestType(source);
20088+
if (genericRestType) {
20089+
return genericRestType;
2009020090
}
2009120091
}
2009220092
const start = hasRest ? Math.min(pos, paramCount - 1) : pos;
@@ -20136,11 +20136,11 @@ namespace ts {
2013620136
return signature.minArgumentCount;
2013720137
}
2013820138

20139-
function getRestTypeParameter(signature: Signature) {
20139+
function getGenericRestType(signature: Signature) {
2014020140
if (signature.hasRestParameter) {
2014120141
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
20142-
if (restType.flags & TypeFlags.TypeParameter) {
20143-
return <TypeParameter>restType;
20142+
if (restType.flags & TypeFlags.Instantiable) {
20143+
return restType;
2014420144
}
2014520145
}
2014620146
return undefined;

0 commit comments

Comments
 (0)