@@ -856,6 +856,8 @@ type Checker struct {
856856 skipDirectInferenceNodes collections.Set[*ast.Node]
857857 ctx context.Context
858858 packagesMap map[string]bool
859+ activeMappers []*TypeMapper
860+ activeTypeMappersCaches []map[string]*Type
859861}
860862
861863func NewChecker(program Program) *Checker {
@@ -21178,14 +21180,66 @@ func (c *Checker) instantiateTypeWithAlias(t *Type, m *TypeMapper, alias *TypeAl
2117821180 c.error(c.currentNode, diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite)
2117921181 return c.errorType
2118021182 }
21183+ index := c.findActiveMapper(m)
21184+ if index == -1 {
21185+ c.pushActiveMapper(m)
21186+ }
21187+ var b KeyBuilder
21188+ b.WriteType(t)
21189+ b.WriteAlias(alias)
21190+ key := b.String()
21191+ cache := c.activeTypeMappersCaches[core.IfElse(index != -1, index, len(c.activeTypeMappersCaches)-1)]
21192+ if cachedType, ok := cache[key]; ok {
21193+ return cachedType
21194+ }
2118121195 c.TotalInstantiationCount++
2118221196 c.instantiationCount++
2118321197 c.instantiationDepth++
2118421198 result := c.instantiateTypeWorker(t, m, alias)
21199+ if index == -1 {
21200+ c.popActiveMapper()
21201+ } else {
21202+ cache[key] = result
21203+ }
2118521204 c.instantiationDepth--
2118621205 return result
2118721206}
2118821207
21208+ func (c *Checker) pushActiveMapper(mapper *TypeMapper) {
21209+ c.activeMappers = append(c.activeMappers, mapper)
21210+
21211+ lastIndex := len(c.activeTypeMappersCaches)
21212+ if cap(c.activeTypeMappersCaches) > lastIndex {
21213+ // The cap may contain an empty map from popActiveMapper; reuse it.
21214+ c.activeTypeMappersCaches = c.activeTypeMappersCaches[:lastIndex+1]
21215+ if c.activeTypeMappersCaches[lastIndex] == nil {
21216+ c.activeTypeMappersCaches[lastIndex] = make(map[string]*Type, 1)
21217+ }
21218+ } else {
21219+ c.activeTypeMappersCaches = append(c.activeTypeMappersCaches, make(map[string]*Type, 1))
21220+ }
21221+ }
21222+
21223+ func (c *Checker) popActiveMapper() {
21224+ c.activeMappers[len(c.activeMappers)-1] = nil
21225+ c.activeMappers = c.activeMappers[:len(c.activeMappers)-1]
21226+
21227+ // Clear the map, but leave it in the list for later reuse.
21228+ lastIndex := len(c.activeTypeMappersCaches) - 1
21229+ clear(c.activeTypeMappersCaches[lastIndex])
21230+ c.activeTypeMappersCaches = c.activeTypeMappersCaches[:lastIndex]
21231+ }
21232+
21233+ func (c *Checker) findActiveMapper(mapper *TypeMapper) int {
21234+ return core.FindLastIndex(c.activeMappers, func(m *TypeMapper) bool { return m == mapper })
21235+ }
21236+
21237+ func (c *Checker) clearActiveMapperCaches() {
21238+ for _, cache := range c.activeTypeMappersCaches {
21239+ clear(cache)
21240+ }
21241+ }
21242+
2118921243// Return true if the given type could possibly reference a type parameter for which
2119021244// we perform type inference (i.e. a type parameter of a generic function). We cache
2119121245// results for union and intersection types for performance reasons.
0 commit comments