@@ -67,6 +67,7 @@ namespace ts {
6767 let enumCount = 0;
6868 let instantiationDepth = 0;
6969 let constraintDepth = 0;
70+ let currentNode: Node | undefined;
7071
7172 const emptySymbols = createSymbolTable();
7273 const identityMapper: (type: Type) => Type = identity;
@@ -7525,6 +7526,7 @@ namespace ts {
75257526 // very high likelyhood we're dealing with an infinite generic type that perpetually generates
75267527 // new type identities as we descend into it. We stop the recursion here and mark this type
75277528 // and the outer types as having circular constraints.
7529+ error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
75287530 nonTerminating = true;
75297531 return t.immediateBaseConstraint = noConstraintType;
75307532 }
@@ -9240,18 +9242,6 @@ namespace ts {
92409242 return includes;
92419243 }
92429244
9243- function isSubtypeOfAny(source: Type, targets: ReadonlyArray<Type>): boolean {
9244- for (const target of targets) {
9245- if (source !== target && isTypeSubtypeOf(source, target) && (
9246- !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) ||
9247- !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) ||
9248- isTypeDerivedFrom(source, target))) {
9249- return true;
9250- }
9251- }
9252- return false;
9253- }
9254-
92559245 function isSetOfLiteralsFromSameEnum(types: ReadonlyArray<Type>): boolean {
92569246 const first = types[0];
92579247 if (first.flags & TypeFlags.EnumLiteral) {
@@ -9268,17 +9258,40 @@ namespace ts {
92689258 return false;
92699259 }
92709260
9271- function removeSubtypes(types: Type[]) {
9272- if (types.length === 0 || isSetOfLiteralsFromSameEnum(types)) {
9273- return;
9261+ function removeSubtypes(types: Type[]): boolean {
9262+ const len = types.length;
9263+ if (len === 0 || isSetOfLiteralsFromSameEnum(types)) {
9264+ return true;
92749265 }
9275- let i = types.length;
9266+ let i = len;
9267+ let count = 0;
92769268 while (i > 0) {
92779269 i--;
9278- if (isSubtypeOfAny(types[i], types)) {
9279- orderedRemoveItemAt(types, i);
9270+ const source = types[i];
9271+ for (const target of types) {
9272+ if (source !== target) {
9273+ if (count === 10000) {
9274+ // After 10000 subtype checks we estimate the remaining amount of work by assuming the
9275+ // same ratio of checks to removals. If the estimated number of remaining type checks is
9276+ // greater than 1000000 we deem the union type too complex to represent.
9277+ const estimatedCount = (count / (len - i)) * len;
9278+ if (estimatedCount > 1000000) {
9279+ error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
9280+ return false;
9281+ }
9282+ }
9283+ count++;
9284+ if (isTypeSubtypeOf(source, target) && (
9285+ !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) ||
9286+ !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) ||
9287+ isTypeDerivedFrom(source, target))) {
9288+ orderedRemoveItemAt(types, i);
9289+ break;
9290+ }
9291+ }
92809292 }
92819293 }
9294+ return true;
92829295 }
92839296
92849297 function removeRedundantLiteralTypes(types: Type[], includes: TypeFlags) {
@@ -9325,7 +9338,9 @@ namespace ts {
93259338 }
93269339 break;
93279340 case UnionReduction.Subtype:
9328- removeSubtypes(typeSet);
9341+ if (!removeSubtypes(typeSet)) {
9342+ return errorType;
9343+ }
93299344 break;
93309345 }
93319346 if (typeSet.length === 0) {
@@ -10957,6 +10972,7 @@ namespace ts {
1095710972 // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
1095810973 // with a combination of infinite generic types that perpetually generate new type identities. We stop
1095910974 // the recursion here by yielding the error type.
10975+ error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
1096010976 return errorType;
1096110977 }
1096210978 instantiationDepth++;
@@ -23063,7 +23079,7 @@ namespace ts {
2306323079 return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
2306423080 }
2306523081
23066- function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, checkMode?: CheckMode) {
23082+ function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName , type: Type, checkMode?: CheckMode) {
2306723083 if (checkMode === CheckMode.Inferential) {
2306823084 const signature = getSingleCallSignature(type);
2306923085 if (signature && signature.typeParameters) {
@@ -23133,15 +23149,10 @@ namespace ts {
2313323149 // have the wildcard function type; this form of type check is used during overload resolution to exclude
2313423150 // contextually typed function and arrow expressions in the initial phase.
2313523151 function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type {
23136- let type: Type;
23137- if (node.kind === SyntaxKind.QualifiedName) {
23138- type = checkQualifiedName(<QualifiedName>node);
23139- }
23140- else {
23141- const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
23142- type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
23143- }
23144-
23152+ const saveCurrentNode = currentNode;
23153+ currentNode = node;
23154+ const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
23155+ const type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
2314523156 if (isConstEnumObjectType(type)) {
2314623157 // enum object type for const enums are only permitted in:
2314723158 // - 'left' in property access
@@ -23157,6 +23168,7 @@ namespace ts {
2315723168 error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query);
2315823169 }
2315923170 }
23171+ currentNode = saveCurrentNode;
2316023172 return type;
2316123173 }
2316223174
@@ -23168,7 +23180,7 @@ namespace ts {
2316823180 return checkExpression(node.expression, checkMode);
2316923181 }
2317023182
23171- function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined, forceTuple?: boolean): Type {
23183+ function checkExpressionWorker(node: Expression | QualifiedName , checkMode: CheckMode | undefined, forceTuple?: boolean): Type {
2317223184 switch (node.kind) {
2317323185 case SyntaxKind.Identifier:
2317423186 return checkIdentifier(<Identifier>node);
@@ -23201,6 +23213,8 @@ namespace ts {
2320123213 return checkObjectLiteral(<ObjectLiteralExpression>node, checkMode);
2320223214 case SyntaxKind.PropertyAccessExpression:
2320323215 return checkPropertyAccessExpression(<PropertyAccessExpression>node);
23216+ case SyntaxKind.QualifiedName:
23217+ return checkQualifiedName(<QualifiedName>node);
2320423218 case SyntaxKind.ElementAccessExpression:
2320523219 return checkIndexedAccess(<ElementAccessExpression>node);
2320623220 case SyntaxKind.CallExpression:
@@ -27882,10 +27896,15 @@ namespace ts {
2788227896 }
2788327897
2788427898 function checkSourceElement(node: Node | undefined): void {
27885- if (!node) {
27886- return;
27899+ if (node) {
27900+ const saveCurrentNode = currentNode;
27901+ currentNode = node;
27902+ checkSourceElementWorker(node);
27903+ currentNode = saveCurrentNode;
2788727904 }
27905+ }
2788827906
27907+ function checkSourceElementWorker(node: Node): void {
2788927908 if (isInJSFile(node)) {
2789027909 forEach((node as JSDocContainer).jsDoc, ({ tags }) => forEach(tags, checkSourceElement));
2789127910 }
@@ -28143,32 +28162,36 @@ namespace ts {
2814328162
2814428163 function checkDeferredNodes(context: SourceFile) {
2814528164 const links = getNodeLinks(context);
28146- if (! links.deferredNodes) {
28147- return ;
28165+ if (links.deferredNodes) {
28166+ links.deferredNodes.forEach(checkDeferredNode) ;
2814828167 }
28149- links.deferredNodes.forEach(node => {
28150- switch (node.kind) {
28151- case SyntaxKind.FunctionExpression:
28152- case SyntaxKind.ArrowFunction:
28153- case SyntaxKind.MethodDeclaration:
28154- case SyntaxKind.MethodSignature:
28155- checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
28156- break;
28157- case SyntaxKind.GetAccessor:
28158- case SyntaxKind.SetAccessor:
28159- checkAccessorDeclaration(<AccessorDeclaration>node);
28160- break;
28161- case SyntaxKind.ClassExpression:
28162- checkClassExpressionDeferred(<ClassExpression>node);
28163- break;
28164- case SyntaxKind.JsxSelfClosingElement:
28165- checkJsxSelfClosingElementDeferred(<JsxSelfClosingElement>node);
28166- break;
28167- case SyntaxKind.JsxElement:
28168- checkJsxElementDeferred(<JsxElement>node);
28169- break;
28170- }
28171- });
28168+ }
28169+
28170+ function checkDeferredNode(node: Node) {
28171+ const saveCurrentNode = currentNode;
28172+ currentNode = node;
28173+ switch (node.kind) {
28174+ case SyntaxKind.FunctionExpression:
28175+ case SyntaxKind.ArrowFunction:
28176+ case SyntaxKind.MethodDeclaration:
28177+ case SyntaxKind.MethodSignature:
28178+ checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
28179+ break;
28180+ case SyntaxKind.GetAccessor:
28181+ case SyntaxKind.SetAccessor:
28182+ checkAccessorDeclaration(<AccessorDeclaration>node);
28183+ break;
28184+ case SyntaxKind.ClassExpression:
28185+ checkClassExpressionDeferred(<ClassExpression>node);
28186+ break;
28187+ case SyntaxKind.JsxSelfClosingElement:
28188+ checkJsxSelfClosingElementDeferred(<JsxSelfClosingElement>node);
28189+ break;
28190+ case SyntaxKind.JsxElement:
28191+ checkJsxElementDeferred(<JsxElement>node);
28192+ break;
28193+ }
28194+ currentNode = saveCurrentNode;
2817228195 }
2817328196
2817428197 function checkSourceFile(node: SourceFile) {
0 commit comments