@@ -20303,16 +20303,6 @@ func (c *Checker) yieldCycle(start int) bool {
2030320303 return true
2030420304}
2030520305
20306- // observeHiddenMembers fails the cycle yield in progress if the members of t
20307- // are being resolved below it. Members are made available while they are
20308- // resolved, so the yield would see whatever part of them the hidden
20309- // resolution has published, rather than compute them from scratch.
20310- func (c *Checker) observeHiddenMembers(t *Type) {
20311- if i, ok := c.resolving.get(memoKeyOf(t, memoStructuredMembers)); ok && int(i) < c.visibleStart {
20312- c.markResolutionCycle(c.visibleStart)
20313- }
20314- }
20315-
2031620306// yieldCycleToMembers handles re-entering the type resolution in progress
2031720307// at start, a cycle that would fail it, when the cycle passes through a
2031820308// member table. Entering the cycle at the member table instead would not
@@ -21127,7 +21117,7 @@ func (c *Checker) isApplicableIndexType(source *Type, target *Type) bool {
2112721117}
2112821118
2112921119func (c *Checker) resolveStructuredTypeMembers(t *Type) *StructuredType {
21130- if t.objectFlags&( ObjectFlagsMembersResolved|ObjectFlagsMembersResolving) == ObjectFlagsMembersResolved && !c.observingMemos {
21120+ if t.objectFlags&ObjectFlagsMembersResolved != 0 && !c.observingMemos {
2113121121 return t.asResolvedStructuredType()
2113221122 }
2113321123 return c.resolveStructuredTypeMembersSlow(t)
@@ -21137,12 +21127,16 @@ func (c *Checker) resolveStructuredTypeMembers(t *Type) *StructuredType {
2113721127// past reading resolved members, out of line so that the rest inlines.
2113821128func (c *Checker) resolveStructuredTypeMembersSlow(t *Type) *StructuredType {
2113921129 key := memoKeyOf(t, memoStructuredMembers)
21140- if t.objectFlags&( ObjectFlagsMembersResolved|ObjectFlagsMembersResolving) == ObjectFlagsMembersResolved {
21130+ if t.objectFlags&ObjectFlagsMembersResolved != 0 {
2114121131 // Resolved members are only read.
2114221132 c.observeMemo(key)
2114321133 return t.AsStructuredType()
2114421134 }
21145- if t.objectFlags&ObjectFlagsMembersResolving != 0 {
21135+ published := false
21136+ enclosing, inProgress := c.resolvingAnyIndex(key)
21137+ if !inProgress {
21138+ enclosing = -1
21139+ } else {
2114621140 // Resolving members may observe the type itself, whose members are
2114721141 // then incomplete.
2114821142 if c.isModuleTableType(t) {
@@ -21153,59 +21147,88 @@ func (c *Checker) resolveStructuredTypeMembersSlow(t *Type) *StructuredType {
2115321147 c.addCycleParticipants(start)
2115421148 }
2115521149 }
21156- if len(c.cycleYields) != 0 {
21157- c.observeHiddenMembers(t)
21150+ if j, ok := c.resolving.get(key); ok && int(j) < c.visibleStart {
21151+ // The members are being resolved below the cycle yield in
21152+ // progress, which then sees whatever part of them that
21153+ // resolution has published, rather than compute them from
21154+ // scratch, so the yield fails.
21155+ c.markResolutionCycle(c.visibleStart)
2115821156 }
21157+ published = c.resolutions[enclosing].membersPublished
2115921158 }
2116021159 c.beginMemo(key)
21161- result := c.resolveStructuredTypeMembersUncached(t)
21160+ if !published {
21161+ c.resolveStructuredTypeMembersUncached(t, enclosing)
21162+ }
2116221163 c.endMemo()
21163- return result
21164+ return t.AsStructuredType()
2116421165}
2116521166
21166- func (c *Checker) resolveStructuredTypeMembersUncached(t *Type) *StructuredType {
21167- if t.objectFlags&ObjectFlagsMembersResolved == 0 {
21168- if t.objectFlags&ObjectFlagsMembersResolving == 0 && c.isModuleTableType(t) {
21169- c.resolveModuleTableMembers(t)
21170- return t.AsStructuredType()
21167+ // resolveStructuredTypeMembersUncached resolves the members of t in the memo
21168+ // just begun for them. Many kinds of types make members available before
21169+ // they are complete, through publishStructuredTypeMembers, so the resolution
21170+ // is on the stack, but never fails. The members are resolved only once the
21171+ // outermost resolution of them completes. A nested one, which re-entering
21172+ // the members before any are available starts, makes its result available
21173+ // to the rest of the enclosing resolution at index enclosing, which may be
21174+ // hidden by a cycle yield.
21175+ func (c *Checker) resolveStructuredTypeMembersUncached(t *Type, enclosing int) {
21176+ outermost := enclosing < 0
21177+ if outermost && c.isModuleTableType(t) {
21178+ c.resolveModuleTableMembers(t)
21179+ return
21180+ }
21181+ c.beginTypeResolution(t, TypeSystemPropertyNameStructuredMembers)
21182+ defer func() {
21183+ c.popTypeResolution()
21184+ if outermost {
21185+ t.objectFlags |= ObjectFlagsMembersResolved
21186+ } else {
21187+ c.resolutions[enclosing].membersPublished = true
2117121188 }
21172- // Many kinds of types make members available before they are
21173- // complete, so the resolution is on the stack, but never fails.
21174- outermost := t.objectFlags&ObjectFlagsMembersResolving == 0
21175- t.objectFlags |= ObjectFlagsMembersResolving
21176- c.beginTypeResolution(t, TypeSystemPropertyNameStructuredMembers)
21177- defer func() {
21178- c.popTypeResolution()
21179- if outermost {
21180- t.objectFlags &^= ObjectFlagsMembersResolving
21181- }
21182- if c.logResults() {
21183- c.logMembersDiscard(t)
21184- }
21185- }()
21189+ if c.logResults() {
21190+ c.logMembersDiscard(t)
21191+ }
21192+ }()
21193+ switch {
21194+ case t.flags&TypeFlagsObject != 0:
2118621195 switch {
21187- case t.flags&TypeFlagsObject != 0:
21188- switch {
21189- case t.objectFlags&(ObjectFlagsClassOrInterface|ObjectFlagsReference) != 0:
21190- c.resolveObjectTypeMembers(t)
21191- case t.objectFlags&ObjectFlagsReverseMapped != 0:
21192- c.resolveReverseMappedTypeMembers(t)
21193- case t.objectFlags&ObjectFlagsAnonymous != 0:
21194- c.resolveAnonymousTypeMembers(t)
21195- case t.objectFlags&ObjectFlagsMapped != 0:
21196- c.resolveMappedTypeMembers(t)
21197- default:
21198- panic("Unhandled case in resolveStructuredTypeMembers")
21199- }
21200- case t.flags&TypeFlagsUnion != 0:
21201- c.resolveUnionTypeMembers(t)
21202- case t.flags&TypeFlagsIntersection != 0:
21203- c.resolveIntersectionTypeMembers(t)
21196+ case t.objectFlags&(ObjectFlagsClassOrInterface|ObjectFlagsReference) != 0:
21197+ c.resolveObjectTypeMembers(t)
21198+ case t.objectFlags&ObjectFlagsReverseMapped != 0:
21199+ c.resolveReverseMappedTypeMembers(t)
21200+ case t.objectFlags&ObjectFlagsAnonymous != 0:
21201+ c.resolveAnonymousTypeMembers(t)
21202+ case t.objectFlags&ObjectFlagsMapped != 0:
21203+ c.resolveMappedTypeMembers(t)
2120421204 default:
2120521205 panic("Unhandled case in resolveStructuredTypeMembers")
2120621206 }
21207+ case t.flags&TypeFlagsUnion != 0:
21208+ c.resolveUnionTypeMembers(t)
21209+ case t.flags&TypeFlagsIntersection != 0:
21210+ c.resolveIntersectionTypeMembers(t)
21211+ default:
21212+ panic("Unhandled case in resolveStructuredTypeMembers")
2120721213 }
21208- return t.AsStructuredType()
21214+ }
21215+
21216+ // markMembersPublished records that the members of t, whose resolution is
21217+ // in progress, are available to computations re-entering it.
21218+ func (c *Checker) markMembersPublished(t *Type) {
21219+ i, ok := c.resolvingAnyIndex(memoKeyOf(t, memoStructuredMembers))
21220+ debug.Assert(ok, "members published outside their resolution")
21221+ c.resolutions[i].membersPublished = true
21222+ }
21223+
21224+ // publishStructuredTypeMembers sets the members of t while they are being
21225+ // resolved, making them available to computations re-entering the resolution
21226+ // before it completes.
21227+ func (c *Checker) publishStructuredTypeMembers(t *Type, members ast.SymbolTable, callSignatures []*Signature, constructSignatures []*Signature, indexInfos []*IndexInfo) {
21228+ // Listing the properties may re-enter the resolution, which then sees
21229+ // the members.
21230+ c.markMembersPublished(t)
21231+ c.setStructuredTypeData(t, members, callSignatures, constructSignatures, indexInfos)
2120921232}
2121021233
2121121234// isModuleTableType reports whether t is the type of a module object, whose
@@ -21253,7 +21276,6 @@ func (c *Checker) resolveModuleTableMembers(t *Type) {
2125321276 mark := c.markDiscard()
2125421277 hidden := false
2125521278 for {
21256- t.objectFlags |= ObjectFlagsMembersResolving
2125721279 c.beginTypeResolution(t, TypeSystemPropertyNameStructuredMembers)
2125821280 c.resolveAnonymousTypeMembers(t)
2125921281 r := c.topTypeResolution()
@@ -21268,11 +21290,13 @@ func (c *Checker) resolveModuleTableMembers(t *Type) {
2126821290 c.discardSince(mark)
2126921291 }
2127021292 c.popTypeResolution()
21271- t.objectFlags &^= ObjectFlagsMembersResolving
2127221293 if canonical == nil && !restart {
2127321294 break
2127421295 }
2127521296 c.clearStructuredMembers(t)
21297+ key := memoKeyOf(t, memoStructuredMembers)
21298+ i, _ := c.resolving.get(key)
21299+ c.resolutions[i].membersPublished = false
2127621300 if canonical != nil {
2127721301 c.resolveStructuredTypeMembers(canonical.(*Type))
2127821302 continue
@@ -21281,12 +21305,12 @@ func (c *Checker) resolveModuleTableMembers(t *Type) {
2128121305 // is resolved again as if it had been entered first: with the
2128221306 // computations in progress below it hidden.
2128321307 hidden = true
21284- floor, _ := c.resolving.get(memoKeyOf(t, memoStructuredMembers))
21285- c.beginCycleYield(t, TypeSystemPropertyNameStructuredMembers, -1, int(floor))
21308+ c.beginCycleYield(t, TypeSystemPropertyNameStructuredMembers, -1, int(i))
2128621309 }
2128721310 if hidden {
2128821311 c.endCycleYield()
2128921312 }
21313+ t.objectFlags |= ObjectFlagsMembersResolved
2129021314 c.releaseDiscardMark(mark)
2129121315 if c.logResults() {
2129221316 c.logMembersDiscard(t)
@@ -21312,7 +21336,7 @@ func (c *Checker) clearStructuredMembers(t *Type) {
2131221336//go:noinline
2131321337func (c *Checker) logMembersDiscard(t *Type) {
2131421338 c.discardLog = append(c.discardLog, discardEntry{nil, func() {
21315- if t.objectFlags&ObjectFlagsMembersResolving != 0 {
21339+ if _, ok := c.resolvingAnyIndex(memoKeyOf(t, memoStructuredMembers)); ok {
2131621340 // An enclosing resolution of the same members sets them again.
2131721341 return
2131821342 }
@@ -21398,7 +21422,7 @@ func (c *Checker) resolveObjectTypeMembers(t *Type) {
2139821422 return findIndexInfo(indexInfos, info.keyType) == nil
2139921423 }))
2140021424 }
21401- c.setStructuredTypeMembers (t, nil, callSignatures, constructSignatures, indexInfos)
21425+ c.setStructuredTypeData (t, nil, callSignatures, constructSignatures, indexInfos)
2140221426 lazyState := c.lazyStateArena.New()
2140321427 lazyState.layout = layout
2140421428 lazyState.mapper = mapper
@@ -23101,22 +23125,22 @@ func (c *Checker) instantiateIndexInfo(info *IndexInfo, m *TypeMapper) *IndexInf
2310123125func (c *Checker) resolveAnonymousTypeMembers(t *Type) {
2310223126 d := t.AsObjectType()
2310323127 if d.target != nil {
23104- c.setStructuredTypeMembers (t, nil, nil, nil, nil)
23128+ c.publishStructuredTypeMembers (t, nil, nil, nil, nil)
2310523129 members := c.createInstantiatedSymbolTable(c.getPropertiesOfObjectType(d.target), d.mapper)
2310623130 callSignatures := c.instantiateSignatures(c.getSignaturesOfType(d.target, SignatureKindCall), d.mapper)
2310723131 constructSignatures := c.instantiateSignatures(c.getSignaturesOfType(d.target, SignatureKindConstruct), d.mapper)
2310823132 indexInfos := c.instantiateIndexInfos(c.getIndexInfosOfType(d.target), d.mapper)
23109- c.setStructuredTypeMembers (t, members, callSignatures, constructSignatures, indexInfos)
23133+ c.publishStructuredTypeMembers (t, members, callSignatures, constructSignatures, indexInfos)
2311023134 return
2311123135 }
2311223136 symbol := c.getMergedSymbol(t.symbol)
2311323137 if symbol.Flags()&ast.SymbolFlagsTypeLiteral != 0 {
23114- c.setStructuredTypeMembers (t, nil, nil, nil, nil)
23138+ c.publishStructuredTypeMembers (t, nil, nil, nil, nil)
2311523139 members := c.getMembersOfSymbol(symbol)
2311623140 callSignatures := c.getSignaturesOfSymbol(members.Get(ast.InternalSymbolNameCall))
2311723141 constructSignatures := c.getSignaturesOfSymbol(members.Get(ast.InternalSymbolNameNew))
2311823142 indexInfos := c.getIndexInfosOfSymbol(symbol)
23119- c.setStructuredTypeMembers (t, members, callSignatures, constructSignatures, indexInfos)
23143+ c.publishStructuredTypeMembers (t, members, callSignatures, constructSignatures, indexInfos)
2312023144 return
2312123145 }
2312223146 // Combinations of function, class, enum and module
@@ -23132,14 +23156,14 @@ func (c *Checker) resolveAnonymousTypeMembers(t *Type) {
2313223156 members = varsOnly
2313323157 }
2313423158 var baseConstructorIndexInfo *IndexInfo
23135- c.setStructuredTypeMembers (t, members, nil, nil, nil)
23159+ c.publishStructuredTypeMembers (t, members, nil, nil, nil)
2313623160 if symbol.Flags()&ast.SymbolFlagsClass != 0 {
2313723161 classType := c.getDeclaredTypeOfClassOrInterface(symbol)
2313823162 baseConstructorType := c.getBaseConstructorTypeOfClass(classType)
2313923163 if baseConstructorType.flags&(TypeFlagsObject|TypeFlagsIntersection|TypeFlagsTypeVariable) != 0 {
2314023164 members = members.Clone()
2314123165 c.addInheritedMembers(members, c.getPropertiesOfType(baseConstructorType))
23142- c.setStructuredTypeMembers (t, members, nil, nil, nil)
23166+ c.publishStructuredTypeMembers (t, members, nil, nil, nil)
2314323167 } else if baseConstructorType == c.anyType {
2314423168 baseConstructorIndexInfo = c.anyBaseTypeIndexInfo
2314523169 }
@@ -23351,7 +23375,7 @@ func (c *Checker) resolveMappedTypeMembers(t *Type) {
2335123375 members := ast.NewSymbolTable()
2335223376 var indexInfos []*IndexInfo
2335323377 // Resolve upfront such that recursive references see an empty object type.
23354- c.setStructuredTypeMembers (t, nil, nil, nil, nil)
23378+ c.publishStructuredTypeMembers (t, nil, nil, nil, nil)
2335523379 // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type,
2335623380 // and T as the template type.
2335723381 typeParameter := c.getTypeParameterFromMappedType(t)
@@ -23434,7 +23458,7 @@ func (c *Checker) resolveMappedTypeMembers(t *Type) {
2343423458 } else {
2343523459 forEachType(c.getLowerBoundOfKeyType(constraintType), addMemberForKeyType)
2343623460 }
23437- c.setStructuredTypeMembers (t, members, nil, nil, indexInfos)
23461+ c.publishStructuredTypeMembers (t, members, nil, nil, indexInfos)
2343823462}
2343923463
2344023464func (c *Checker) getTypeOfMappedSymbol(symbol *ast.Symbol) *Type {
@@ -23521,7 +23545,7 @@ func (c *Checker) resolveUnionTypeMembers(t *Type) {
2352123545 return c.getSignaturesOfType(t, SignatureKindConstruct)
2352223546 }))
2352323547 indexInfos := c.getUnionIndexInfos(t.Types())
23524- c.setStructuredTypeMembers (t, nil, callSignatures, constructSignatures, indexInfos)
23548+ c.setStructuredTypeData (t, nil, callSignatures, constructSignatures, indexInfos)
2352523549}
2352623550
2352723551func (c *Checker) getArrayMemberCallSignatures(t *Type) []*Signature {
@@ -23785,7 +23809,7 @@ func (c *Checker) resolveIntersectionTypeMembers(t *Type) {
2378523809 indexInfos = c.appendIndexInfo(indexInfos, info, false /*union*/)
2378623810 }
2378723811 }
23788- c.setStructuredTypeMembers (t, nil, callSignatures, constructSignatures, indexInfos)
23812+ c.setStructuredTypeData (t, nil, callSignatures, constructSignatures, indexInfos)
2378923813}
2379023814
2379123815func (c *Checker) appendSignatures(signatures []*Signature, newSignatures []*Signature) []*Signature {
@@ -28030,8 +28054,14 @@ func (c *Checker) cloneTypeReference(source *Type) *Type {
2803028054 return t
2803128055}
2803228056
28057+ // setStructuredTypeMembers sets the members of a type being created, which
28058+ // are then resolved.
2803328059func (c *Checker) setStructuredTypeMembers(t *Type, members ast.SymbolTable, callSignatures []*Signature, constructSignatures []*Signature, indexInfos []*IndexInfo) {
2803428060 t.objectFlags |= ObjectFlagsMembersResolved
28061+ c.setStructuredTypeData(t, members, callSignatures, constructSignatures, indexInfos)
28062+ }
28063+
28064+ func (c *Checker) setStructuredTypeData(t *Type, members ast.SymbolTable, callSignatures []*Signature, constructSignatures []*Signature, indexInfos []*IndexInfo) {
2803528065 data := t.AsStructuredType()
2803628066 data.members = members
2803728067 data.properties = c.getNamedMembers(members, t.symbol)
0 commit comments