Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Higher order function type inference#30215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ahejlsberg merged 20 commits intomasterfromhigherOrderFunctionTypeInference
Mar 8, 2019
Merged
Changes from1 commit
Commits
Show all changes
20 commits
Select commitHold shift + click to select a range
b44bfaa
Convert CheckMode to a flags style enum
ahejlsbergFeb 28, 2019
23473e0
Skip generic functions along with context sensitive arguments
ahejlsbergMar 1, 2019
db5ca33
Merge branch 'master' into deferGenericFunctionInference
ahejlsbergMar 1, 2019
35ebbec
Minor fixes
ahejlsbergMar 1, 2019
91f8fc6
Defer calls to generic functions returning generic functions
ahejlsbergMar 2, 2019
304e25c
Add tests
ahejlsbergMar 2, 2019
e7881a4
Accept new baselines
ahejlsbergMar 2, 2019
c344ef3
Infer higher order function types when possible
ahejlsbergMar 3, 2019
c58819e
Accept new baselines
ahejlsbergMar 4, 2019
919ade1
Improve scheme for creating unique type parameter names
ahejlsbergMar 4, 2019
549c684
Minor fix
ahejlsbergMar 4, 2019
22c934a
Add tests
ahejlsbergMar 4, 2019
5fe8ebb
Accept new baselines
ahejlsbergMar 4, 2019
bf326aa
Fix lint error
ahejlsbergMar 4, 2019
ad823da
Consistently defer generic functions to second type inference pass
ahejlsbergMar 5, 2019
cde9444
Accept new baselines
ahejlsbergMar 5, 2019
6c790c0
Remove unnecessary excludeArgument array and getExcludeArgument function
ahejlsbergMar 5, 2019
6d88251
Minor change to heuristic for deferring generic calls
ahejlsbergMar 6, 2019
b34fe67
Fix issue of more inferences leading to worse results
ahejlsbergMar 6, 2019
a9e924b
Fix check for function type (allow checked type to have overloads)
ahejlsbergMar 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Defer calls to generic functions returning generic functions
  • Loading branch information
@ahejlsberg
ahejlsberg committedMar 2, 2019
commit91f8fc60f1b0cc42c7842d71ee5fe7a0b2f37595
86 changes: 53 additions & 33 deletionssrc/compiler/checker.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -228,9 +228,9 @@ namespace ts {
isContextSensitive,
getFullyQualifiedName,
getResolvedSignature: (node, candidatesOutArray, agumentCount) =>
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount,/*isForSignatureHelp*/ false),
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount,CheckMode.Normal),
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, agumentCount) =>
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount,/*isForSignatureHelp*/ true),
getResolvedSignatureWorker(node, candidatesOutArray, agumentCount,CheckMode.IsForSignatureHelp),
getConstantValue: nodeIn => {
const node = getParseTreeNode(nodeIn, canHaveConstantValue);
return node ? getConstantValue(node) : undefined;
Expand DownExpand Up@@ -374,10 +374,10 @@ namespace ts {
getLocalTypeParametersOfClassOrInterfaceOrTypeAlias,
};

function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined,isForSignatureHelp: boolean): Signature | undefined {
function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined,checkMode: CheckMode): Signature | undefined {
const node = getParseTreeNode(nodeIn, isCallLikeExpression);
apparentArgumentCount = argumentCount;
const res = node ? getResolvedSignature(node, candidatesOutArray,isForSignatureHelp) : undefined;
const res = node ? getResolvedSignature(node, candidatesOutArray,checkMode) : undefined;
apparentArgumentCount = undefined;
return res;
}
Expand DownExpand Up@@ -693,6 +693,7 @@ namespace ts {
Inferential = 1 << 1, // Inferential typing
SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
}

const enum CallbackCheck {
Expand DownExpand Up@@ -20482,7 +20483,7 @@ namespace ts {
return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount);
}

function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray<Signature>, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean, fallbackError?: DiagnosticMessage): Signature {
function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray<Signature>, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode, fallbackError?: DiagnosticMessage): Signature {
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
const isDecorator = node.kind === SyntaxKind.Decorator;
const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);
Expand DownExpand Up@@ -20555,7 +20556,7 @@ namespace ts {
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
// so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
const signatureHelpTrailingComma =
isForSignatureHelp && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma;
!!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma;

// Section 4.12.1:
// if the candidate list contains one or more signatures for which the type of each argument
Expand DownExpand Up@@ -20837,7 +20838,7 @@ namespace ts {
return maxParamsIndex;
}

function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean): Signature {
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode): Signature {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
const superType = checkSuperExpression(node.expression);
if (isTypeAny(superType)) {
Expand All@@ -20852,7 +20853,7 @@ namespace ts {
const baseTypeNode = getEffectiveBaseTypeNode(getContainingClass(node)!);
if (baseTypeNode) {
const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode);
return resolveCall(node, baseConstructors, candidatesOutArray,isForSignatureHelp);
return resolveCall(node, baseConstructors, candidatesOutArray,checkMode);
}
}
return resolveUntypedCall(node);
Expand DownExpand Up@@ -20912,12 +20913,22 @@ namespace ts {
}
return resolveErrorCall(node);
}
// If we are skipping generic functions (i.e. this call is an argument to another call for which context
// sensitive arguments are being deferred) and every call signature is generic and returns a function type,
// we return resolvingSignature here. This result will be propagated out and turned into anyFunctionType.
if (checkMode & CheckMode.SkipGenericFunctions && callSignatures.every(isGenericFunctionReturningFunction)) {
return resolvingSignature;
}
// If the function is explicitly marked with `@class`, then it must be constructed.
if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) {
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp);
return resolveCall(node, callSignatures, candidatesOutArray, checkMode);
}

function isGenericFunctionReturningFunction(signature: Signature) {
return !!(signature.typeParameters && getSingleCallSignature(getReturnTypeOfSignature(signature)));
}

/**
Expand All@@ -20931,7 +20942,7 @@ namespace ts {
!numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType);
}

function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean): Signature {
function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode): Signature {
if (node.arguments && languageVersion < ScriptTarget.ES5) {
const spreadIndex = getSpreadArgumentIndex(node.arguments);
if (spreadIndex >= 0) {
Expand DownExpand Up@@ -20984,7 +20995,7 @@ namespace ts {
return resolveErrorCall(node);
}

return resolveCall(node, constructSignatures, candidatesOutArray,isForSignatureHelp);
return resolveCall(node, constructSignatures, candidatesOutArray,checkMode);
}

// If expressionType's apparent type is an object type with no construct signatures but
Expand All@@ -20993,7 +21004,7 @@ namespace ts {
// operation is Any. It is an error to have a Void this type.
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
if (callSignatures.length) {
const signature = resolveCall(node, callSignatures, candidatesOutArray,isForSignatureHelp);
const signature = resolveCall(node, callSignatures, candidatesOutArray,checkMode);
if (!noImplicitAny) {
if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
Expand DownExpand Up@@ -21103,7 +21114,7 @@ namespace ts {
}
}

function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean): Signature {
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode): Signature {
const tagType = checkExpression(node.tag);
const apparentType = getApparentType(tagType);

Expand All@@ -21124,7 +21135,7 @@ namespace ts {
return resolveErrorCall(node);
}

return resolveCall(node, callSignatures, candidatesOutArray,isForSignatureHelp);
return resolveCall(node, callSignatures, candidatesOutArray,checkMode);
}

/**
Expand DownExpand Up@@ -21155,7 +21166,7 @@ namespace ts {
/**
* Resolves a decorator as if it were a call expression.
*/
function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean): Signature {
function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode): Signature {
const funcType = checkExpression(node.expression);
const apparentType = getApparentType(funcType);
if (apparentType === errorType) {
Expand DownExpand Up@@ -21184,7 +21195,7 @@ namespace ts {
return resolveErrorCall(node);
}

return resolveCall(node, callSignatures, candidatesOutArray,isForSignatureHelp, headMessage);
return resolveCall(node, callSignatures, candidatesOutArray,checkMode, headMessage);
}

function createSignatureForJSXIntrinsic(node: JsxOpeningLikeElement, result: Type): Signature {
Expand DownExpand Up@@ -21213,7 +21224,7 @@ namespace ts {
);
}

function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean): Signature {
function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode): Signature {
if (isJsxIntrinsicIdentifier(node.tagName)) {
const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
const fakeSignature = createSignatureForJSXIntrinsic(node, result);
Expand All@@ -21237,7 +21248,7 @@ namespace ts {
return resolveErrorCall(node);
}

return resolveCall(node, signatures, candidatesOutArray,isForSignatureHelp);
return resolveCall(node, signatures, candidatesOutArray,checkMode);
}

/**
Expand All@@ -21252,19 +21263,19 @@ namespace ts {
signature.parameters.length < getDecoratorArgumentCount(decorator, signature));
}

function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined,isForSignatureHelp: boolean): Signature {
function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined,checkMode: CheckMode): Signature {
switch (node.kind) {
case SyntaxKind.CallExpression:
return resolveCallExpression(node, candidatesOutArray,isForSignatureHelp);
return resolveCallExpression(node, candidatesOutArray,checkMode);
case SyntaxKind.NewExpression:
return resolveNewExpression(node, candidatesOutArray,isForSignatureHelp);
return resolveNewExpression(node, candidatesOutArray,checkMode);
case SyntaxKind.TaggedTemplateExpression:
return resolveTaggedTemplateExpression(node, candidatesOutArray,isForSignatureHelp);
return resolveTaggedTemplateExpression(node, candidatesOutArray,checkMode);
case SyntaxKind.Decorator:
return resolveDecorator(node, candidatesOutArray,isForSignatureHelp);
return resolveDecorator(node, candidatesOutArray,checkMode);
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
return resolveJsxOpeningLikeElement(node, candidatesOutArray,isForSignatureHelp);
return resolveJsxOpeningLikeElement(node, candidatesOutArray,checkMode);
}
throw Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable.");
}
Expand All@@ -21276,7 +21287,7 @@ namespace ts {
* the function will fill it up with appropriate candidate signatures
* @return a signature of the call-like expression or undefined if one can't be found
*/
function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined,isForSignatureHelp = false): Signature {
function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined,checkMode?: CheckMode): Signature {
const links = getNodeLinks(node);
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
// However, it is possible that either candidatesOutArray was not passed in the first time,
Expand All@@ -21287,11 +21298,15 @@ namespace ts {
return cached;
}
links.resolvedSignature = resolvingSignature;
const result = resolveSignature(node, candidatesOutArray, isForSignatureHelp);
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
// types from the control flow analysis.
links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached;
const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
// When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
// resolution should be deferred.
if (result !== resolvingSignature) {
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
// types from the control flow analysis.
links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached;
}
return result;
}

Expand DownExpand Up@@ -21375,10 +21390,15 @@ namespace ts {
* @param node The call/new expression to be checked.
* @returns On success, the expression's signature's return type. On failure, anyType.
*/
function checkCallExpression(node: CallExpression | NewExpression): Type {
function checkCallExpression(node: CallExpression | NewExpression, checkMode?: CheckMode): Type {
if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments);

const signature = getResolvedSignature(node);
const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode);
if (signature === resolvingSignature) {
// CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that
// returns a function type. We defer checking and return anyFunctionType.
return anyFunctionType;
}

if (node.expression.kind === SyntaxKind.SuperKeyword) {
return voidType;
Expand DownExpand Up@@ -23505,7 +23525,7 @@ namespace ts {
}
/* falls through */
case SyntaxKind.NewExpression:
return checkCallExpression(<CallExpression>node);
return checkCallExpression(<CallExpression>node, checkMode);
case SyntaxKind.TaggedTemplateExpression:
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.ParenthesizedExpression:
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp