@@ -4263,27 +4263,27 @@ namespace ts {
42634263 // TYPE CHECKING
42644264
42654265 function isTypeIdenticalTo(source: Type, target: Type): boolean {
4266- return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
4266+ return checkTypeRelatedTo(source, target, identityRelation, RelationComparisonFlags.None, /*errorNode*/ undefined);
42674267 }
42684268
42694269 function compareTypes(source: Type, target: Type): Ternary {
4270- return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False;
4270+ return checkTypeRelatedTo(source, target, identityRelation, RelationComparisonFlags.None, /*errorNode*/ undefined) ? Ternary.True : Ternary.False;
42714271 }
42724272
42734273 function isTypeSubtypeOf(source: Type, target: Type): boolean {
42744274 return checkTypeSubtypeOf(source, target, /*errorNode*/ undefined);
42754275 }
42764276
42774277 function isTypeAssignableTo(source: Type, target: Type): boolean {
4278- return checkTypeAssignableTo(source, target, /*errorNode*/ undefined);
4278+ return checkTypeAssignableTo(source, target, RelationComparisonFlags.None, /*errorNode*/ undefined);
42794279 }
42804280
42814281 function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
4282- return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
4282+ return checkTypeRelatedTo(source, target, subtypeRelation, RelationComparisonFlags.None, errorNode, headMessage, containingMessageChain);
42834283 }
42844284
4285- function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
4286- return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain);
4285+ function checkTypeAssignableTo(source: Type, target: Type, relationFlags: RelationComparisonFlags, errorNode? : Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
4286+ return checkTypeRelatedTo(source, target, assignableRelation, relationFlags, errorNode, headMessage, containingMessageChain);
42874287 }
42884288
42894289 function isSignatureAssignableTo(source: Signature, target: Signature): boolean {
@@ -4292,13 +4292,30 @@ namespace ts {
42924292 return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined);
42934293 }
42944294
4295+ /**
4296+ * Checks if 'source' is related to 'target' (e.g.: is a assignable to).
4297+ * @param source The left-hand-side of the relation.
4298+ * @param target The right-hand-side of the relation.
4299+ * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', or 'subTypeRelation'.
4300+ * Used as both to determine which checks are performed and as a cache of previously computed results.
4301+ * @param relationFlags Additional information affecting whether the relation holds. Currently used only for distinguishing
4302+ * between a type comparison when extending classes from other comparisons of the constructor types.
4303+ *
4304+ * Caution: checks triggered by these flags should NOT affect the result re
4305+ * @param errorNode The node upon which all errors will be reported, if defined.
4306+ * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used.
4307+ * @param containingMessageChain A chain of errors to prepend any new errors found.
4308+
4309+ */
42954310 function checkTypeRelatedTo(
42964311 source: Type,
42974312 target: Type,
42984313 relation: Map<RelationComparisonResult>,
4299- errorNode: Node,
4314+ relationFlags: RelationComparisonFlags,
4315+ errorNode?: Node,
43004316 headMessage?: DiagnosticMessage,
4301- containingMessageChain?: DiagnosticMessageChain): boolean {
4317+ containingMessageChain?: DiagnosticMessageChain
4318+ ): boolean {
43024319
43034320 let errorInfo: DiagnosticMessageChain;
43044321 let sourceStack: ObjectType[];
@@ -7212,6 +7229,7 @@ namespace ts {
72127229 typeArgumentsAreAssignable = checkTypeAssignableTo(
72137230 typeArgument,
72147231 constraint,
7232+ RelationComparisonFlags.None,
72157233 reportErrors ? typeArgNode : undefined,
72167234 typeArgumentHeadMessage,
72177235 errorInfo);
@@ -7243,7 +7261,7 @@ namespace ts {
72437261 // Use argument expression as error location when reporting errors
72447262 let errorNode = reportErrors ? getEffectiveArgumentErrorNode(node, i, arg) : undefined;
72457263 let headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
7246- if (!checkTypeRelatedTo(argType, paramType, relation, errorNode, headMessage)) {
7264+ if (!checkTypeRelatedTo(argType, paramType, relation, RelationComparisonFlags.None, errorNode, headMessage)) {
72477265 return false;
72487266 }
72497267 }
@@ -8040,7 +8058,7 @@ namespace ts {
80408058 if (produceDiagnostics && targetType !== unknownType) {
80418059 let widenedType = getWidenedType(exprType);
80428060 if (!(isTypeAssignableTo(targetType, widenedType))) {
8043- checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
8061+ checkTypeAssignableTo(exprType, targetType, RelationComparisonFlags.None, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
80448062 }
80458063 }
80468064 return targetType;
@@ -8274,7 +8292,7 @@ namespace ts {
82748292 else {
82758293 let exprType = checkExpression(<Expression>node.body);
82768294 if (node.type) {
8277- checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
8295+ checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), RelationComparisonFlags.None, node.body, /*headMessage*/ undefined);
82788296 }
82798297 checkFunctionAndClassExpressionBodies(node.body);
82808298 }
@@ -8582,7 +8600,7 @@ namespace ts {
85828600 function checkReferenceAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type {
85838601 let targetType = checkExpression(target, contextualMapper);
85848602 if (checkReferenceExpression(target, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant)) {
8585- checkTypeAssignableTo(sourceType, targetType, target, /*headMessage*/ undefined);
8603+ checkTypeAssignableTo(sourceType, targetType, RelationComparisonFlags.None, target, /*headMessage*/ undefined);
85868604 }
85878605 return sourceType;
85888606 }
@@ -8757,7 +8775,7 @@ namespace ts {
87578775 // Use default messages
87588776 if (ok) {
87598777 // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
8760- checkTypeAssignableTo(valueType, leftType, node.left, /*headMessage*/ undefined);
8778+ checkTypeAssignableTo(valueType, leftType, RelationComparisonFlags.None, node.left, /*headMessage*/ undefined);
87618779 }
87628780 }
87638781 }
@@ -8808,10 +8826,10 @@ namespace ts {
88088826 if (func.type) {
88098827 let signatureElementType = getElementTypeOfIterableIterator(getTypeFromTypeNode(func.type)) || anyType;
88108828 if (nodeIsYieldStar) {
8811- checkTypeAssignableTo(expressionElementType, signatureElementType, node.expression, /*headMessage*/ undefined);
8829+ checkTypeAssignableTo(expressionElementType, signatureElementType, RelationComparisonFlags.None, node.expression, /*headMessage*/ undefined);
88128830 }
88138831 else {
8814- checkTypeAssignableTo(expressionType, signatureElementType, node.expression, /*headMessage*/ undefined);
8832+ checkTypeAssignableTo(expressionType, signatureElementType, RelationComparisonFlags.None, node.expression, /*headMessage*/ undefined);
88158833 }
88168834 }
88178835 }
@@ -9119,7 +9137,7 @@ namespace ts {
91199137 else {
91209138 checkTypeAssignableTo(typePredicate.type,
91219139 getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
9122- typePredicateNode.type);
9140+ RelationComparisonFlags.None, typePredicateNode.type);
91239141 }
91249142 }
91259143 else if (typePredicateNode.parameterName) {
@@ -9197,7 +9215,7 @@ namespace ts {
91979215 // interface BadGenerator extends Iterable<number>, Iterator<string> { }
91989216 // function* g(): BadGenerator { } // Iterable and Iterator have different types!
91999217 //
9200- checkTypeAssignableTo(iterableIteratorInstantiation, returnType, node.type);
9218+ checkTypeAssignableTo(iterableIteratorInstantiation, returnType, RelationComparisonFlags.None, node.type);
92019219 }
92029220 }
92039221 }
@@ -9399,7 +9417,7 @@ namespace ts {
93999417 let constraint = getConstraintOfTypeParameter(typeParameters[i]);
94009418 if (constraint) {
94019419 let typeArgument = typeArguments[i];
9402- result = result && checkTypeAssignableTo(getTypeFromTypeNode(typeArgument), constraint, typeArgument, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
9420+ result = result && checkTypeAssignableTo(getTypeFromTypeNode(typeArgument), constraint, RelationComparisonFlags.None, typeArgument, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
94039421 }
94049422 }
94059423 return result;
@@ -9836,6 +9854,7 @@ namespace ts {
98369854 checkTypeAssignableTo(
98379855 returnType,
98389856 expectedReturnType,
9857+ RelationComparisonFlags.None,
98399858 node,
98409859 headMessage,
98419860 errorInfo);
@@ -10257,7 +10276,7 @@ namespace ts {
1025710276 // For a binding pattern, validate the initializer and exit
1025810277 if (isBindingPattern(node.name)) {
1025910278 if (node.initializer) {
10260- checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined);
10279+ checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), RelationComparisonFlags.None, node, /*headMessage*/ undefined);
1026110280 checkParameterInitializer(node);
1026210281 }
1026310282 return;
@@ -10267,7 +10286,7 @@ namespace ts {
1026710286 if (node === symbol.valueDeclaration) {
1026810287 // Node is the primary declaration of the symbol, just validate the initializer
1026910288 if (node.initializer) {
10270- checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, /*headMessage*/ undefined);
10289+ checkTypeAssignableTo(checkExpressionCached(node.initializer), type, RelationComparisonFlags.None, node, /*headMessage*/ undefined);
1027110290 checkParameterInitializer(node);
1027210291 }
1027310292 }
@@ -10279,7 +10298,7 @@ namespace ts {
1027910298 error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, declarationNameToString(node.name), typeToString(type), typeToString(declarationType));
1028010299 }
1028110300 if (node.initializer) {
10282- checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined);
10301+ checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, RelationComparisonFlags.None, node, /*headMessage*/ undefined);
1028310302 }
1028410303 }
1028510304 if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature) {
@@ -10331,7 +10350,7 @@ namespace ts {
1033110350
1033210351 function checkExpressionStatement(node: ExpressionStatement) {
1033310352 // Grammar checking
10334- checkGrammarStatementInAmbientContext(node)
10353+ checkGrammarStatementInAmbientContext(node);
1033510354
1033610355 checkExpression(node.expression);
1033710356 }
@@ -10415,7 +10434,7 @@ namespace ts {
1041510434 // because we accessed properties from anyType, or it may have led to an error inside
1041610435 // getElementTypeOfIterable.
1041710436 if (iteratedType) {
10418- checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
10437+ checkTypeAssignableTo(iteratedType, leftType, RelationComparisonFlags.None, varExpr, /*headMessage*/ undefined);
1041910438 }
1042010439 }
1042110440 }
@@ -10515,7 +10534,7 @@ namespace ts {
1051510534 // Now even though we have extracted the iteratedType, we will have to validate that the type
1051610535 // passed in is actually an Iterable.
1051710536 if (errorNode && elementType) {
10518- checkTypeAssignableTo(iterable, createIterableType(elementType), errorNode);
10537+ checkTypeAssignableTo(iterable, createIterableType(elementType), RelationComparisonFlags.None, errorNode);
1051910538 }
1052010539
1052110540 return elementType || anyType;
@@ -10759,7 +10778,7 @@ namespace ts {
1075910778 }
1076010779 }
1076110780 else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func) || signature.typePredicate) {
10762- checkTypeAssignableTo(exprType, returnType, node.expression, /*headMessage*/ undefined);
10781+ checkTypeAssignableTo(exprType, returnType, RelationComparisonFlags.None, node.expression, /*headMessage*/ undefined);
1076310782 }
1076410783 }
1076510784 }
@@ -10802,7 +10821,7 @@ namespace ts {
1080210821 let caseType = checkExpression(caseClause.expression);
1080310822 if (!isTypeAssignableTo(expressionType, caseType)) {
1080410823 // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails
10805- checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
10824+ checkTypeAssignableTo(caseType, expressionType, RelationComparisonFlags.None, caseClause.expression, /*headMessage*/ undefined);
1080610825 }
1080710826 }
1080810827 forEach(clause.statements, checkSourceElement);
@@ -11043,8 +11062,8 @@ namespace ts {
1104311062 }
1104411063 }
1104511064 }
11046- checkTypeAssignableTo(type, baseType, node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
11047- checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
11065+ checkTypeAssignableTo(type, baseType, RelationComparisonFlags.None, node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
11066+ checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), RelationComparisonFlags.ExtendingClass, node.name || node,
1104811067 Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
1104911068 if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class)) {
1105011069 // When the static base type is a "class-like" constructor function (but not actually a class), we verify
@@ -11072,7 +11091,7 @@ namespace ts {
1107211091 if (t !== unknownType) {
1107311092 let declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
1107411093 if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
11075- checkTypeAssignableTo(type, t, node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
11094+ checkTypeAssignableTo(type, t, RelationComparisonFlags.None, node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
1107611095 }
1107711096 else {
1107811097 error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
@@ -11255,7 +11274,7 @@ namespace ts {
1125511274 // run subsequent checks only if first set succeeded
1125611275 if (checkInheritedPropertiesAreIdentical(type, node.name)) {
1125711276 forEach(getBaseTypes(type), baseType => {
11258- checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
11277+ checkTypeAssignableTo(type, baseType, RelationComparisonFlags.None, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
1125911278 });
1126011279 checkIndexConstraints(type);
1126111280 }
@@ -11308,7 +11327,7 @@ namespace ts {
1130811327 // If it is a constant value (not undefined), it is syntactically constrained to be a number.
1130911328 // Also, we do not need to check this for ambients because there is already
1131011329 // a syntax error if it is not a constant.
11311- checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*headMessage*/ undefined);
11330+ checkTypeAssignableTo(checkExpression(initializer), enumType, RelationComparisonFlags.None, initializer, /*headMessage*/ undefined);
1131211331 }
1131311332 }
1131411333 else if (enumIsConst) {
0 commit comments