Skip to content

Commit b53491c

Browse files
committed
Include all excluded arguments in one go instead of one by one
1 parent ad63468 commit b53491c

File tree

1 file changed

+9
-34
lines changed

1 file changed

+9
-34
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18593,8 +18593,6 @@ namespace ts {
1859318593
inferTypes(context.inferences, thisArgumentType, thisType);
1859418594
}
1859518595

18596-
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
18597-
// wildcards for all context sensitive function expressions.
1859818596
const effectiveArgCount = getEffectiveArgumentCount(node, args, signature);
1859918597
const genericRestType = getGenericRestType(signature);
1860018598
const argCount = genericRestType ? Math.min(getParameterCount(signature) - 1, effectiveArgCount) : effectiveArgCount;
@@ -18621,21 +18619,6 @@ namespace ts {
1862118619
inferTypes(context.inferences, spreadType, genericRestType);
1862218620
}
1862318621

18624-
// In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this
18625-
// time treating function expressions normally (which may cause previously inferred type arguments to be fixed
18626-
// as we construct types for contextually typed parameters)
18627-
// Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed.
18628-
// Tagged template expressions will always have `undefined` for `excludeArgument[0]`.
18629-
if (excludeArgument) {
18630-
for (let i = 0; i < argCount; i++) {
18631-
// No need to check for omitted args and template expressions, their exclusion value is always undefined
18632-
if (excludeArgument[i] === false) {
18633-
const arg = args[i];
18634-
const paramType = getTypeAtPosition(signature, i);
18635-
inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType);
18636-
}
18637-
}
18638-
}
1863918622
return getInferredTypes(context);
1864018623
}
1864118624

@@ -19205,23 +19188,20 @@ namespace ts {
1920519188

1920619189
const args = getEffectiveCallArguments(node);
1920719190

19208-
// The following applies to any value of 'excludeArgument[i]':
19209-
// - true: the argument at 'i' is susceptible to a one-time permanent contextual typing.
19210-
// - undefined: the argument at 'i' is *not* susceptible to permanent contextual typing.
19211-
// - false: the argument at 'i' *was* and *has been* permanently contextually typed.
19191+
// The excludeArgument array contains true for each context sensitive argument (an argument
19192+
// is context sensitive it is susceptible to a one-time permanent contextual typing).
1921219193
//
1921319194
// The idea is that we will perform type argument inference & assignability checking once
19214-
// without using the susceptible parameters that are functions, and once more for each of those
19195+
// without using the susceptible parameters that are functions, and once more for those
1921519196
// parameters, contextually typing each as we go along.
1921619197
//
19217-
// For a tagged template, then the first argument be 'undefined' if necessary
19218-
// because it represents a TemplateStringsArray.
19198+
// For a tagged template, then the first argument be 'undefined' if necessary because it
19199+
// represents a TemplateStringsArray.
1921919200
//
1922019201
// For a decorator, no arguments are susceptible to contextual typing due to the fact
1922119202
// decorators are applied to a declaration by the emitter, and not to an expression.
1922219203
const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
1922319204
let excludeArgument: boolean[] | undefined;
19224-
let excludeCount = 0;
1922519205
if (!isDecorator && !isSingleNonGenericCandidate) {
1922619206
// We do not need to call `getEffectiveArgumentCount` here as it only
1922719207
// applies when calculating the number of arguments for a decorator.
@@ -19231,7 +19211,6 @@ namespace ts {
1923119211
excludeArgument = new Array(args!.length);
1923219212
}
1923319213
excludeArgument[i] = true;
19234-
excludeCount++;
1923519214
}
1923619215
}
1923719216
}
@@ -19379,17 +19358,13 @@ namespace ts {
1937919358
candidateForArgumentError = candidate;
1938019359
break;
1938119360
}
19382-
if (excludeCount === 0) {
19361+
// If no arguments were excluded, we're done
19362+
if (!excludeArgument) {
1938319363
candidates[candidateIndex] = candidate;
1938419364
return candidate;
1938519365
}
19386-
excludeCount--;
19387-
if (excludeCount > 0) {
19388-
excludeArgument![excludeArgument!.indexOf(/*value*/ true)] = false;
19389-
}
19390-
else {
19391-
excludeArgument = undefined;
19392-
}
19366+
// Otherwise, stop excluding arguments and perform a second pass
19367+
excludeArgument = undefined;
1939319368
}
1939419369
}
1939519370

0 commit comments

Comments
 (0)