Skip to content

Commit 2aa9fe4

Browse files
committed
Only collect outermost intra expression inference sites
1 parent 04d4580 commit 2aa9fe4

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

src/compiler/checker.ts

+25-14
Original file line numberDiff line numberDiff line change
@@ -1255,9 +1255,10 @@ export const enum CheckMode {
12551255
Inferential = 1 << 1, // Inferential typing
12561256
SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
12571257
SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
1258-
IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
1259-
IsForStringLiteralArgumentCompletions = 1 << 5, // Do not infer from the argument currently being typed
1260-
RestBindingElement = 1 << 6, // Checking a type that is going to be used to determine the type of a rest binding element
1258+
SkipAddingIntraExpressionSites = 1 << 4, // Skip adding intra expression sites in nested expressions since only the outermost one has to be added
1259+
IsForSignatureHelp = 1 << 5, // Call resolution for purposes of signature help
1260+
IsForStringLiteralArgumentCompletions = 1 << 6, // Do not infer from the argument currently being typed
1261+
RestBindingElement = 1 << 7, // Checking a type that is going to be used to determine the type of a rest binding element
12611262
// e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`,
12621263
// we need to preserve generic types instead of substituting them for constraints
12631264
}
@@ -29980,10 +29981,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2998029981
elementFlags.push(ElementFlags.Optional);
2998129982
}
2998229983
else {
29983-
const type = checkExpressionForMutableLocation(e, checkMode, forceTuple);
29984+
const shouldAddAsIntraExpressionInferenceSite = inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & (CheckMode.SkipContextSensitive | CheckMode.SkipAddingIntraExpressionSites)) && isContextSensitive(e);
29985+
const elementCheckMode = (checkMode || CheckMode.Normal) | (shouldAddAsIntraExpressionInferenceSite ? CheckMode.SkipAddingIntraExpressionSites : 0);
29986+
29987+
const type = checkExpressionForMutableLocation(e, elementCheckMode, forceTuple);
2998429988
elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
2998529989
elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required);
29986-
if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) {
29990+
if (shouldAddAsIntraExpressionInferenceSite) {
2998729991
const inferenceContext = getInferenceContext(node);
2998829992
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
2998929993
addIntraExpressionInferenceSite(inferenceContext, e, type);
@@ -30106,7 +30110,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3010630110
return links.immediateTarget;
3010730111
}
3010830112

30109-
function checkObjectLiteral(node: ObjectLiteralExpression, checkMode?: CheckMode): Type {
30113+
function checkObjectLiteral(node: ObjectLiteralExpression, checkMode = CheckMode.Normal): Type {
3011030114
const inDestructuringPattern = isAssignmentTarget(node);
3011130115
// Grammar checking
3011230116
checkGrammarObjectLiteralExpression(node, inDestructuringPattern);
@@ -30148,12 +30152,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3014830152
if (memberDecl.kind === SyntaxKind.PropertyAssignment ||
3014930153
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ||
3015030154
isObjectLiteralMethod(memberDecl)) {
30151-
let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) :
30155+
30156+
const shouldAddAsIntraExpressionInferenceSite = contextualType && checkMode & CheckMode.Inferential && !(checkMode & (CheckMode.SkipContextSensitive | CheckMode.SkipAddingIntraExpressionSites)) &&
30157+
(memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl);
30158+
const propCheckMode = checkMode | (shouldAddAsIntraExpressionInferenceSite ? CheckMode.SkipAddingIntraExpressionSites : 0);
30159+
30160+
let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, propCheckMode) :
3015230161
// avoid resolving the left side of the ShorthandPropertyAssignment outside of the destructuring
3015330162
// for error recovery purposes. For example, if a user wrote `{ a = 100 }` instead of `{ a: 100 }`.
3015430163
// we don't want to say "could not find 'a'".
30155-
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) :
30156-
checkObjectLiteralMethod(memberDecl, checkMode);
30164+
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, propCheckMode) :
30165+
checkObjectLiteralMethod(memberDecl, propCheckMode);
3015730166
if (isInJavascript) {
3015830167
const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl);
3015930168
if (jsDocType) {
@@ -30208,8 +30217,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3020830217
member = prop;
3020930218
allPropertiesTable?.set(prop.escapedName, prop);
3021030219

30211-
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
30212-
(memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) {
30220+
if (shouldAddAsIntraExpressionInferenceSite) {
3021330221
const inferenceContext = getInferenceContext(node);
3021430222
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
3021530223
const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl;
@@ -30428,7 +30436,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3042830436
* @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral,
3042930437
* which also calls getSpreadType.
3043030438
*/
30431-
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) {
30439+
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode = CheckMode.Normal) {
3043230440
const attributes = openingLikeElement.attributes;
3043330441
const contextualType = getContextualType(attributes, ContextFlags.None);
3043430442
const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined;
@@ -30443,7 +30451,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3044330451
for (const attributeDecl of attributes.properties) {
3044430452
const member = attributeDecl.symbol;
3044530453
if (isJsxAttribute(attributeDecl)) {
30446-
const exprType = checkJsxAttribute(attributeDecl, checkMode);
30454+
const shouldAddAsIntraExpressionInferenceSite = contextualType && checkMode & CheckMode.Inferential && !(checkMode & (CheckMode.SkipContextSensitive | CheckMode.SkipAddingIntraExpressionSites)) && isContextSensitive(attributeDecl);
30455+
const attributeCheckMode = checkMode | (shouldAddAsIntraExpressionInferenceSite ? CheckMode.SkipAddingIntraExpressionSites : 0);
30456+
30457+
const exprType = checkJsxAttribute(attributeDecl, attributeCheckMode);
3044730458
objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags;
3044830459

3044930460
const attributeSymbol = createSymbol(SymbolFlags.Property | member.flags, member.escapedName);
@@ -30465,7 +30476,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3046530476
addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string);
3046630477
}
3046730478
}
30468-
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) {
30479+
if (shouldAddAsIntraExpressionInferenceSite) {
3046930480
const inferenceContext = getInferenceContext(attributes);
3047030481
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
3047130482
const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!;

0 commit comments

Comments
 (0)