mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-23 18:48:40 -05:00
Optimize checking for signatures with control flow effects
This commit is contained in:
@@ -18580,10 +18580,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getEffectsSignature(node: CallExpression) {
|
||||
function hasEffectsSignature(node: CallExpression) {
|
||||
const links = getNodeLinks(node);
|
||||
let signature = links.effectsSignature;
|
||||
if (signature === undefined) {
|
||||
if (!(links.flags & NodeCheckFlags.EffectsSignatureChecked)) {
|
||||
// A call expression parented by an expression statement is a potential assertion. Other call
|
||||
// expressions are potential type predicate function calls. In order to avoid triggering
|
||||
// circularities in control flow analysis, we use getTypeOfDottedName when resolving the call
|
||||
@@ -18592,12 +18591,9 @@ namespace ts {
|
||||
node.expression.kind !== SyntaxKind.SuperKeyword ? checkNonNullExpression(node.expression) :
|
||||
undefined;
|
||||
const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call);
|
||||
const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] :
|
||||
some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) :
|
||||
undefined;
|
||||
signature = links.effectsSignature = candidate && hasTypePredicateOrNeverReturnType(candidate) ? candidate : unknownSignature;
|
||||
links.flags |= NodeCheckFlags.EffectsSignatureChecked | (some(signatures, hasTypePredicateOrNeverReturnType) ? NodeCheckFlags.HasEffectsSignature : 0);
|
||||
}
|
||||
return signature === unknownSignature ? undefined : signature;
|
||||
return !!(links.flags & NodeCheckFlags.HasEffectsSignature);
|
||||
}
|
||||
|
||||
function hasTypePredicateOrNeverReturnType(signature: Signature) {
|
||||
@@ -18641,8 +18637,8 @@ namespace ts {
|
||||
flow = (<FlowAssignment | FlowCondition | FlowArrayMutation | PreFinallyFlow>flow).antecedent;
|
||||
}
|
||||
else if (flags & FlowFlags.Call) {
|
||||
const signature = getEffectsSignature((<FlowCall>flow).node);
|
||||
if (signature && getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
|
||||
const node = (<FlowCall>flow).node;
|
||||
if (hasEffectsSignature(node) && getReturnTypeOfSignature(getResolvedSignature(node)).flags & TypeFlags.Never) {
|
||||
return false;
|
||||
}
|
||||
flow = (<FlowCall>flow).antecedent;
|
||||
@@ -18894,8 +18890,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTypeAtFlowCall(flow: FlowCall): FlowType | undefined {
|
||||
const signature = getEffectsSignature(flow.node);
|
||||
if (signature) {
|
||||
if (hasEffectsSignature(flow.node)) {
|
||||
const signature = getResolvedSignature(flow.node);
|
||||
const predicate = getTypePredicateOfSignature(signature);
|
||||
if (predicate && (predicate.kind === TypePredicateKind.AssertsThis || predicate.kind === TypePredicateKind.AssertsIdentifier)) {
|
||||
const flowType = getTypeAtFlowNode(flow.antecedent);
|
||||
@@ -19506,9 +19502,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
|
||||
if (hasMatchingArgument(callExpression, reference)) {
|
||||
const signature = getEffectsSignature(callExpression);
|
||||
const predicate = signature && getTypePredicateOfSignature(signature);
|
||||
if (hasMatchingArgument(callExpression, reference) && hasEffectsSignature(callExpression)) {
|
||||
const predicate = getTypePredicateOfSignature(getResolvedSignature(callExpression));
|
||||
if (predicate && (predicate.kind === TypePredicateKind.This || predicate.kind === TypePredicateKind.Identifier)) {
|
||||
return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue);
|
||||
}
|
||||
|
||||
@@ -4028,6 +4028,8 @@ namespace ts {
|
||||
AssignmentsMarked = 0x00800000, // Parameter assignments have been marked
|
||||
ClassWithConstructorReference = 0x01000000, // Class that contains a binding to its constructor inside of the class body.
|
||||
ConstructorReferenceInClass = 0x02000000, // Binding to a class constructor inside of the class's body.
|
||||
EffectsSignatureChecked = 0x04000000, // Node checked for assertion or never-returning signature
|
||||
HasEffectsSignature = 0x08000000, // Node has assertion or never-returning signature
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -4038,7 +4040,6 @@ namespace ts {
|
||||
resolvedSignature?: Signature; // Cached signature of signature node or call expression
|
||||
resolvedSymbol?: Symbol; // Cached name resolution result
|
||||
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
|
||||
effectsSignature?: Signature; // Signature with possible control flow effects
|
||||
enumMemberValue?: string | number; // Constant value of enum member
|
||||
isVisible?: boolean; // Is this node visible
|
||||
containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference
|
||||
|
||||
Reference in New Issue
Block a user