@@ -234,10 +234,9 @@ type IterationTypesKey struct {
234234// PropertiesTypesKey
235235
236236type PropertiesTypesKey struct {
237- typeId TypeId
238- include TypeFlags
239- includeOrigin bool
240- unresolvedMembers bool
237+ typeId TypeId
238+ include TypeFlags
239+ includeOrigin bool
241240}
242241
243242// NonExistentPropertyKey
@@ -596,7 +595,7 @@ type Checker struct {
596595 SignatureCount uint32
597596 TotalInstantiationCount uint32
598597 instantiationCount uint32
599- instantiationDepth uint32
598+ instantiationStack []*Type
600599 conditionalConstraintDepth uint32
601600 inlineLevel int
602601 serializationLevel int
@@ -4724,15 +4723,15 @@ basePropertyCheck:
47244723 c.error(errorNode, diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, memberInfo.typeName, missedProperty, memberInfo.baseTypeName)
47254724 }
47264725 case len(memberInfo.missedProperties) > 5:
4727- missedProperties := strings.Join(core.Map( memberInfo.missedProperties[:4], func(prop string) string { return "'" + prop + "'" }), ", " )
4726+ missedProperties := quotedAndCommaSeparated( memberInfo.missedProperties[:4])
47284727 remainingMissedProperties := len(memberInfo.missedProperties) - 4
47294728 if ast.IsClassExpression(errorNode) {
47304729 c.error(errorNode, diagnostics.Non_abstract_class_expression_is_missing_implementations_for_the_following_members_of_0_Colon_1_and_2_more, memberInfo.baseTypeName, missedProperties, remainingMissedProperties)
47314730 } else {
47324731 c.error(errorNode, diagnostics.Non_abstract_class_0_is_missing_implementations_for_the_following_members_of_1_Colon_2_and_3_more, memberInfo.typeName, memberInfo.baseTypeName, missedProperties, remainingMissedProperties)
47334732 }
47344733 default:
4735- missedProperties := strings.Join(core.Map( memberInfo.missedProperties, func(prop string) string { return "'" + prop + "'" }), ", " )
4734+ missedProperties := quotedAndCommaSeparated( memberInfo.missedProperties)
47364735 if ast.IsClassExpression(errorNode) {
47374736 c.error(errorNode, diagnostics.Non_abstract_class_expression_is_missing_implementations_for_the_following_members_of_0_Colon_1, memberInfo.baseTypeName, missedProperties)
47384737 } else {
@@ -19470,9 +19469,7 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters
1947019469 if !instantiated {
1947119470 members = maps.Clone(members)
1947219471 }
19473- c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos)
1947419472 thisArgument := core.LastOrNil(typeArguments)
19475- t.objectFlags |= ObjectFlagsUnresolvedMembers
1947619473 for _, baseType := range baseTypes {
1947719474 instantiatedBaseType := baseType
1947819475 if thisArgument != nil {
@@ -19491,7 +19488,6 @@ func (c *Checker) resolveObjectTypeMembers(t *Type, source *Type, typeParameters
1949119488 return findIndexInfo(indexInfos, info.keyType) == nil
1949219489 }))
1949319490 }
19494- t.objectFlags &^= ObjectFlagsUnresolvedMembers
1949519491 }
1949619492 c.setStructuredTypeMembers(t, members, callSignatures, constructSignatures, indexInfos)
1949719493}
@@ -22503,14 +22499,22 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl
2250322499 if t == nil || m == nil || !(c.couldContainTypeVariables(t) || (t.alias != nil && len(t.alias.typeArguments) > 0 && core.Some(t.alias.typeArguments, c.couldContainTypeVariables))) {
2250422500 return t
2250522501 }
22506- if c.instantiationDepth == 100 || c.instantiationCount >= 5_000_000 {
22502+ if len(c.instantiationStack) == 100 || c.instantiationCount >= 5_000_000 {
2250722503 // We have reached 100 recursive type instantiations, or 5M type instantiations caused by the same statement
2250822504 // or expression. There is a very high likelihood we're dealing with a combination of infinite generic types
2250922505 // that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
2251022506 if tr := c.tracer; tr != nil {
22511- tr.Instant(tracing.PhaseCheckTypes, "instantiateType_DepthLimit", map[string]any{"typeId": t.id, "instantiationDepth": c.instantiationDepth, "instantiationCount": c.instantiationCount})
22507+ tr.Instant(tracing.PhaseCheckTypes, "instantiateType_DepthLimit", map[string]any{"typeId": t.id, "instantiationDepth": len(c.instantiationStack), "instantiationCount": c.instantiationCount})
22508+ }
22509+ circularTypeNames := c.getCircularTypeNames()
22510+ switch {
22511+ case len(circularTypeNames) == 1:
22512+ c.error(c.currentNode, diagnostics.Instantiations_of_type_0_appear_infinitely_circular, circularTypeNames[0])
22513+ case len(circularTypeNames) > 1:
22514+ c.error(c.currentNode, diagnostics.Instantiations_of_the_following_types_appear_infinitely_circular_Colon_0, quotedAndCommaSeparated(circularTypeNames))
22515+ default:
22516+ c.error(c.currentNode, diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite)
2251222517 }
22513- c.error(c.currentNode, diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite)
2251422518 return c.errorType
2251522519 }
2251622520 index := c.findActiveMapper(m)
@@ -22527,17 +22531,38 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl
2252722531 }
2252822532 c.TotalInstantiationCount++
2252922533 c.instantiationCount++
22530- c.instantiationDepth++
22534+ c.instantiationStack = append(c.instantiationStack, t)
2253122535 result := c.instantiateTypeWorker(t, m, alias)
2253222536 if index == -1 {
2253322537 c.popActiveMapper()
2253422538 } else {
2253522539 cache[key] = result
2253622540 }
22537- c.instantiationDepth--
22541+ c.instantiationStack[len(c.instantiationStack)-1] = nil
22542+ c.instantiationStack = c.instantiationStack[:len(c.instantiationStack)-1]
2253822543 return result
2253922544}
2254022545
22546+ func (c *Checker) getCircularTypeNames() []string {
22547+ typeCounts := make(map[*Type]int)
22548+ var circularTypeNames []string
22549+ for _, t := range c.instantiationStack {
22550+ typeCounts[t] = typeCounts[t] + 1
22551+ if typeCounts[t] == 3 {
22552+ symbol := t.symbol
22553+ if t.alias != nil {
22554+ symbol = t.alias.symbol
22555+ }
22556+ if symbol != nil && len(symbol.Name) != 0 && symbol.Name[0] != '\xFE' {
22557+ if name := c.SymbolToString(symbol); !slices.Contains(circularTypeNames, name) {
22558+ circularTypeNames = append(circularTypeNames, name)
22559+ }
22560+ }
22561+ }
22562+ }
22563+ return circularTypeNames
22564+ }
22565+
2254122566func (c *Checker) pushActiveMapper(mapper *TypeMapper) {
2254222567 c.activeMappers = append(c.activeMappers, mapper)
2254322568
@@ -27155,7 +27180,7 @@ func (c *Checker) getExtractStringType(t *Type) *Type {
2715527180}
2715627181
2715727182func (c *Checker) getLiteralTypeFromProperties(t *Type, include TypeFlags, includeOrigin bool) *Type {
27158- key := PropertiesTypesKey{typeId: t.id, include: include, includeOrigin: includeOrigin, unresolvedMembers: t.objectFlags&ObjectFlagsUnresolvedMembers != 0 }
27183+ key := PropertiesTypesKey{typeId: t.id, include: include, includeOrigin: includeOrigin}
2715927184 if cached, ok := c.propertiesTypes[key]; ok {
2716027185 return cached
2716127186 }
0 commit comments