@@ -323,6 +323,8 @@ namespace ts {
323323 let constraintDepth = 0;
324324 let currentNode: Node | undefined;
325325
326+ const typeCatalog: Type[] = []; // NB: id is index + 1
327+
326328 const emptySymbols = createSymbolTable();
327329 const arrayVariances = [VarianceFlags.Covariant];
328330
@@ -366,6 +368,7 @@ namespace ts {
366368 getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"),
367369 getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
368370 getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount,
371+ getTypeCatalog: () => typeCatalog,
369372 getTypeCount: () => typeCount,
370373 getInstantiationCount: () => totalInstantiationCount,
371374 getRelationCacheSizes: () => ({
@@ -380,6 +383,7 @@ namespace ts {
380383 getMergedSymbol,
381384 getDiagnostics,
382385 getGlobalDiagnostics,
386+ getRecursionIdentity,
383387 getTypeOfSymbolAtLocation: (symbol, locationIn) => {
384388 const location = getParseTreeNode(locationIn);
385389 return location ? getTypeOfSymbolAtLocation(symbol, location) : errorType;
@@ -3674,6 +3678,7 @@ namespace ts {
36743678 const result = new Type(checker, flags);
36753679 typeCount++;
36763680 result.id = typeCount;
3681+ typeCatalog.push(result);
36773682 return result;
36783683 }
36793684
@@ -10847,6 +10852,7 @@ namespace ts {
1084710852 // very high likelihood we're dealing with an infinite generic type that perpetually generates
1084810853 // new type identities as we descend into it. We stop the recursion here and mark this type
1084910854 // and the outer types as having circular constraints.
10855+ tracing.instant(tracing.Phase.Check, "getImmediateBaseConstraint_DepthLimit", { typeId: t.id, originalTypeId: type.id, depth: constraintDepth });
1085010856 error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
1085110857 nonTerminating = true;
1085210858 return t.immediateBaseConstraint = noConstraintType;
@@ -12936,6 +12942,7 @@ namespace ts {
1293612942 // caps union types at 5000 unique literal types and 1000 unique object types.
1293712943 const estimatedCount = (count / (len - i)) * len;
1293812944 if (estimatedCount > (primitivesOnly ? 25000000 : 1000000)) {
12945+ tracing.instant(tracing.Phase.Check, "removeSubtypes_DepthLimit", { typeIds: types.map(t => t.id) });
1293912946 error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
1294012947 return false;
1294112948 }
@@ -15096,6 +15103,7 @@ namespace ts {
1509615103 // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
1509715104 // with a combination of infinite generic types that perpetually generate new type identities. We stop
1509815105 // the recursion here by yielding the error type.
15106+ tracing.instant(tracing.Phase.Check, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount });
1509915107 error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
1510015108 return errorType;
1510115109 }
@@ -16195,6 +16203,7 @@ namespace ts {
1619516203 containingMessageChain?: () => DiagnosticMessageChain | undefined,
1619616204 errorOutputContainer?: { errors?: Diagnostic[], skipLogging?: boolean },
1619716205 ): boolean {
16206+
1619816207 let errorInfo: DiagnosticMessageChain | undefined;
1619916208 let relatedInfo: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined;
1620016209 let maybeKeys: string[];
@@ -16216,6 +16225,7 @@ namespace ts {
1621616225 reportIncompatibleStack();
1621716226 }
1621816227 if (overflow) {
16228+ tracing.instant(tracing.Phase.Check, "checkTypeRelatedTo_DepthLimit", { sourceId: source.id, targetId: target.id, depth });
1621916229 const diag = error(errorNode || currentNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
1622016230 if (errorOutputContainer) {
1622116231 (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
@@ -16257,6 +16267,8 @@ namespace ts {
1625716267 if (errorNode && errorOutputContainer && errorOutputContainer.skipLogging && result === Ternary.False) {
1625816268 Debug.assert(!!errorOutputContainer.errors, "missed opportunity to interact with error.");
1625916269 }
16270+
16271+
1626016272 return result !== Ternary.False;
1626116273
1626216274 function resetErrorInfo(saved: ReturnType<typeof captureErrorCalculationState>) {
@@ -17034,6 +17046,17 @@ namespace ts {
1703417046 return originalHandler!(onlyUnreliable);
1703517047 };
1703617048 }
17049+
17050+ if (expandingFlags === ExpandingFlags.Both) {
17051+ tracing.instant(tracing.Phase.Check, "recursiveTypeRelatedTo_DepthLimit", {
17052+ sourceId: source.id,
17053+ sourceIdStack: sourceStack.map(t => t.id),
17054+ targetId: target.id,
17055+ targetIdStack: targetStack.map(t => t.id),
17056+ depth,
17057+ });
17058+ }
17059+
1703717060 const result = expandingFlags !== ExpandingFlags.Both ? structuredTypeRelatedTo(source, target, reportErrors, intersectionState) : Ternary.Maybe;
1703817061 if (outofbandVarianceMarkerHandler) {
1703917062 outofbandVarianceMarkerHandler = originalHandler;
@@ -17059,6 +17082,13 @@ namespace ts {
1705917082 }
1706017083
1706117084 function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
17085+ tracing.begin(tracing.Phase.Check, "structuredTypeRelatedTo", { sourceId: source.id, targetId: target.id });
17086+ const result = structuredTypeRelatedToWorker(source, target, reportErrors, intersectionState);
17087+ tracing.end();
17088+ return result;
17089+ }
17090+
17091+ function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
1706217092 if (intersectionState & IntersectionState.PropertyCheck) {
1706317093 return propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.None);
1706417094 }
@@ -17517,6 +17547,7 @@ namespace ts {
1751717547 numCombinations *= countTypes(getTypeOfSymbol(sourceProperty));
1751817548 if (numCombinations > 25) {
1751917549 // We've reached the complexity limit.
17550+ tracing.instant(tracing.Phase.Check, "typeRelatedToDiscriminatedType_DepthLimit", { sourceId: source.id, targetId: target.id, numCombinations });
1752017551 return Ternary.False;
1752117552 }
1752217553 }
@@ -18267,6 +18298,7 @@ namespace ts {
1826718298 function getVariancesWorker<TCache extends { variances?: VarianceFlags[] }>(typeParameters: readonly TypeParameter[] = emptyArray, cache: TCache, createMarkerType: (input: TCache, param: TypeParameter, marker: Type) => Type): VarianceFlags[] {
1826818299 let variances = cache.variances;
1826918300 if (!variances) {
18301+ tracing.begin(tracing.Phase.Check, "getVariancesWorker", { arity: typeParameters.length, id: (cache as any).id ?? (cache as any).declaredType?.id ?? -1 });
1827018302 // The emptyArray singleton is used to signal a recursive invocation.
1827118303 cache.variances = emptyArray;
1827218304 variances = [];
@@ -18301,6 +18333,7 @@ namespace ts {
1830118333 variances.push(variance);
1830218334 }
1830318335 cache.variances = variances;
18336+ tracing.end();
1830418337 }
1830518338 return variances;
1830618339 }
@@ -18449,7 +18482,9 @@ namespace ts {
1844918482 for (let i = 0; i < depth; i++) {
1845018483 if (getRecursionIdentity(stack[i]) === identity) {
1845118484 count++;
18452- if (count >= 5) return true;
18485+ if (count >= 5) {
18486+ return true;
18487+ }
1845318488 }
1845418489 }
1845518490 }
@@ -19554,6 +19589,7 @@ namespace ts {
1955419589 inferFromTypes(originalSource, originalTarget);
1955519590
1955619591 function inferFromTypes(source: Type, target: Type): void {
19592+
1955719593 if (!couldContainTypeVariables(target)) {
1955819594 return;
1955919595 }
@@ -21296,6 +21332,7 @@ namespace ts {
2129621332 if (flowDepth === 2000) {
2129721333 // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
2129821334 // and disable further control flow analysis in the containing function or module body.
21335+ tracing.instant(tracing.Phase.Check, "getTypeAtFlowNode_DepthLimit", { flowId: flow.id });
2129921336 flowAnalysisDisabled = true;
2130021337 reportFlowControlError(reference);
2130121338 return errorType;
@@ -30504,6 +30541,7 @@ namespace ts {
3050430541 }
3050530542
3050630543 function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type {
30544+ tracing.begin(tracing.Phase.Check, "checkExpression", { kind: node.kind, pos: node.pos, end: node.end });
3050730545 const saveCurrentNode = currentNode;
3050830546 currentNode = node;
3050930547 instantiationCount = 0;
@@ -30513,6 +30551,7 @@ namespace ts {
3051330551 checkConstEnumAccess(node, type);
3051430552 }
3051530553 currentNode = saveCurrentNode;
30554+ tracing.end();
3051630555 return type;
3051730556 }
3051830557
@@ -33306,8 +33345,10 @@ namespace ts {
3330633345 }
3330733346
3330833347 function checkVariableDeclaration(node: VariableDeclaration) {
33348+ tracing.begin(tracing.Phase.Check, "checkVariableDeclaration", { kind: node.kind, pos: node.pos, end: node.end });
3330933349 checkGrammarVariableDeclaration(node);
33310- return checkVariableLikeDeclaration(node);
33350+ checkVariableLikeDeclaration(node);
33351+ tracing.end();
3331133352 }
3331233353
3331333354 function checkBindingElement(node: BindingElement) {
@@ -36348,10 +36389,12 @@ namespace ts {
3634836389 }
3634936390
3635036391 function checkSourceFile(node: SourceFile) {
36392+ tracing.begin(tracing.Phase.Check, "checkSourceFile", { path: node.path });
3635136393 performance.mark("beforeCheck");
3635236394 checkSourceFileWorker(node);
3635336395 performance.mark("afterCheck");
3635436396 performance.measure("Check", "beforeCheck", "afterCheck");
36397+ tracing.end();
3635536398 }
3635636399
3635736400 function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean {
0 commit comments