@@ -605,7 +605,6 @@ type Checker struct {
605605 SignatureCount uint32
606606 TotalInstantiationCount uint32
607607 instantiationCount uint32
608- complexityLimitNode *ast.Node // node for which a type complexity limit error was already reported
609608 instantiationLimitReportedNode *ast.Node // node for which the instantiation count limit error was already reported
610609 memberLayoutCount uint32
611610 instantiationStack []*Type
@@ -22762,6 +22761,9 @@ func (c *Checker) symbolIsValueEx(symbol *ast.Symbol, includeTypeOnlyMembers boo
2276222761 c.getSymbolFlagsEx(symbol, !includeTypeOnlyMembers, false /*excludeLocalMeanings*/)&ast.SymbolFlagsValue != 0
2276322762}
2276422763
22764+ // The maximum number of type instantiations performed for a single statement or expression.
22765+ const maxInstantiationCount = 5_000_000
22766+
2276522767func (c *Checker) instantiateType(t *Type, m *TypeMapper) *Type {
2276622768 return c.instantiateTypeWithAlias(t, m, nil /*alias*/)
2276722769}
@@ -22773,15 +22775,14 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl
2277322775 if t == nil || m == nil || !(c.couldContainTypeVariables(t) || (t.alias != nil && len(t.alias.typeArguments) > 0 && core.Some(t.alias.typeArguments, c.couldContainTypeVariables))) {
2277422776 return t
2277522777 }
22776- if len(c.instantiationStack) == 100 || c.instantiationCount >= 5_000_000 {
22778+ if len(c.instantiationStack) == 100 || c.instantiationCount >= maxInstantiationCount {
2277722779 // We have reached 100 recursive type instantiations, or 5M type instantiations caused by the same statement
2277822780 // or expression. There is a very high likelihood we're dealing with a combination of infinite generic types
2277922781 // that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
2278022782 if tr := c.tracer; tr != nil {
2278122783 tr.Instant(tracing.PhaseCheckTypes, "instantiateType_DepthLimit", map[string]any{"typeId": t.id, "instantiationDepth": len(c.instantiationStack), "instantiationCount": c.instantiationCount})
2278222784 }
22783- if c.instantiationCount >= 5_000_000 {
22784- c.complexityLimitNode = c.currentNode
22785+ if c.instantiationCount >= maxInstantiationCount {
2278522786 // Once the count limit is exceeded every further instantiation for this node hits the limit again.
2278622787 // Report the error only once per node instead of allocating millions of identical diagnostics.
2278722788 if c.instantiationLimitReportedNode == c.currentNode && c.currentNode != nil {
@@ -27442,7 +27443,6 @@ func (c *Checker) checkCrossProductUnion(types []*Type) bool {
2744227443 tr.Instant(tracing.PhaseCheckTypes, "checkCrossProductUnion_DepthLimit", map[string]any{"size": size})
2744327444 }
2744427445 c.error(c.currentNode, diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent)
27445- c.complexityLimitNode = c.currentNode
2744627446 return false
2744727447 }
2744827448 return true
@@ -29965,8 +29965,9 @@ func (c *Checker) getTemplateLiteralType(texts []string, types []*Type) *Type {
2996529965 return t.flags&(TypeFlagsNever|TypeFlagsUnion) != 0
2996629966 })
2996729967 if unionIndex >= 0 {
29968- if c.complexityLimitNode != nil && c.complexityLimitNode == c.currentNode {
29969- // A complexity error was already reported for this node. Expanding further cross products
29968+ if c.instantiationCount >= maxInstantiationCount {
29969+ // The instantiation count limit was already exceeded for the current statement or expression, so
29970+ // instantiateType yields the error type for everything from here on. Expanding further cross products
2997029971 // would only allocate huge unions of string literals that can never be used.
2997129972 return c.errorType
2997229973 }
0 commit comments