@@ -19443,7 +19443,7 @@ func (c *Checker) resolveClassOrInterfaceMembers(t *Type) {
1944319443}
1944419444
1944519445func (c *Checker) resolveTypeReferenceMembers(t *Type) {
19446- if lm := c.lazyMemberTables[t]; lm != nil && lm.state != lazyMembersResolvingDeclared {
19446+ if lm := c.lazyMemberTables[t]; lm != nil && lm.ready {
1944719447 c.resolveLazyMembers(t, lm)
1944819448 return
1944919449 }
@@ -19530,35 +19530,20 @@ func (c *Checker) appendInheritedSignaturesAndIndexInfos(callSignatures []*Signa
1953019530// getIndexInfosOfStructuredType answer from the table. Member lookups
1953119531// instantiate only the requested member, the way resolveObjectTypeMembers
1953219532// would have when the table was prepared, and resolving the members in full
19533- // later reuses the symbols already handed out.
19534- //
19535- // While resolveObjectTypeMembers resolves base types, the type exposes its
19536- // declared members (see ObjectFlagsUnresolvedMembers). If preparing the table
19537- // leads back to the type, the type is resolved in full at that point so it
19538- // exposes the same members.
19539-
19540- type lazyMembersState int
19541-
19542- const (
19543- lazyMembersResolvingDeclared lazyMembersState = iota // instantiating declared signatures and index infos, resolving base types
19544- lazyMembersResolvingBases // instantiating base types and resolving their members
19545- lazyMembersReady
19546- lazyMembersMaterialized // resolved in full while base types were being resolved
19547- )
19533+ // later reuses the symbols already handed out. While a table is being
19534+ // prepared, the type resolves its members as usual.
1954819535
1954919536type lazyMemberTable struct {
19550- state lazyMembersState
19537+ ready bool
1955119538 mapper *TypeMapper
1955219539 typeArguments []*Type
1955319540 unaffected []string // sorted names of declared members that instantiate to themselves
19554- callSignatures []*Signature // declared, and once the table is ready, inherited
19541+ callSignatures []*Signature // declared and inherited
1955519542 constructSignatures []*Signature
1955619543 indexInfos []*IndexInfo
1955719544 baseTypes []*Type // instantiated base types
19558- inheritedCount int // number of base types inherited from so far
1955919545 declared map[string]*ast.Symbol
1956019546 found map[string]*ast.Symbol // memoized lookups; nil means no such member
19561- members ast.SymbolTable // once materialized
1956219547}
1956319548
1956419549// isUnresolvedInstantiatedReference reports whether t is a reference to a
@@ -19590,38 +19575,9 @@ func (c *Checker) getReferenceMemberTypeArguments(t *Type, source *Type) (typePa
1959019575 return typeParameters, typeArguments
1959119576}
1959219577
19593- // getLazyMemberTable returns the lazy member table of t, preparing it first if
19594- // needed, or nil if t's members aren't resolved lazily. A table returned while
19595- // it is still being prepared isn't ready.
19596- func (c *Checker) getLazyMemberTable(t *Type) *lazyMemberTable {
19597- if !isUnresolvedInstantiatedReference(t) {
19598- return nil
19599- }
19600- if lm := c.lazyMemberTables[t]; lm != nil {
19601- return lm
19602- }
19603- typeParameters, typeArguments := c.getReferenceMemberTypeArguments(t, t.Target())
19604- if slices.Equal(typeParameters, typeArguments) {
19605- return nil
19606- }
19607- // Resolving deferred type arguments may have led to t being resolved or
19608- // prepared already. Like resolveObjectTypeMembers, which would then replace
19609- // those members, prepare t (again) regardless.
19610- lm := &lazyMemberTable{
19611- mapper: newTypeMapper(typeParameters, typeArguments),
19612- typeArguments: typeArguments,
19613- declared: map[string]*ast.Symbol{},
19614- found: map[string]*ast.Symbol{},
19615- }
19616- c.lazyMemberTables[t] = lm
19617- c.prepareLazyMembers(t, lm)
19618- if lm.state != lazyMembersReady {
19619- return nil
19620- }
19621- return lm
19622- }
19623-
19624- // getReadyLazyMemberTable returns the lazy member table of t if it is ready.
19578+ // getReadyLazyMemberTable returns the lazy member table of t, preparing it
19579+ // first if needed, or nil if t's members aren't resolved lazily or the table
19580+ // is still being prepared.
1962519581func (c *Checker) getReadyLazyMemberTable(t *Type) *lazyMemberTable {
1962619582 if !mayHaveLazyMembers(t) {
1962719583 return nil
@@ -19630,15 +19586,34 @@ func (c *Checker) getReadyLazyMemberTable(t *Type) *lazyMemberTable {
1963019586}
1963119587
1963219588func (c *Checker) getReadyLazyMemberTableWorker(t *Type) *lazyMemberTable {
19633- if lm := c.getLazyMemberTable (t); lm != nil && lm.state == lazyMembersReady {
19634- return lm
19589+ if !isUnresolvedInstantiatedReference (t) {
19590+ return nil
1963519591 }
19636- return nil
19592+ lm := c.lazyMemberTables[t]
19593+ if lm == nil {
19594+ typeParameters, typeArguments := c.getReferenceMemberTypeArguments(t, t.Target())
19595+ if slices.Equal(typeParameters, typeArguments) {
19596+ return nil
19597+ }
19598+ lm = &lazyMemberTable{
19599+ mapper: newTypeMapper(typeParameters, typeArguments),
19600+ typeArguments: typeArguments,
19601+ declared: map[string]*ast.Symbol{},
19602+ found: map[string]*ast.Symbol{},
19603+ }
19604+ c.lazyMemberTables[t] = lm
19605+ c.prepareLazyMembers(t, lm)
19606+ }
19607+ if !lm.ready || t.objectFlags&ObjectFlagsMembersResolved != 0 {
19608+ return nil
19609+ }
19610+ return lm
1963719611}
1963819612
19639- // prepareLazyMembers mirrors resolveObjectTypeMembers, except that it only
19640- // records which declared members would instantiate to themselves instead of
19641- // instantiating them, and doesn't inherit members.
19613+ // prepareLazyMembers mirrors resolveObjectTypeMembers, except that it records
19614+ // which declared members would instantiate to themselves instead of
19615+ // instantiating them, and doesn't inherit members from base types with lazy
19616+ // member tables.
1964219617func (c *Checker) prepareLazyMembers(t *Type, lm *lazyMemberTable) {
1964319618 source := t.Target()
1964419619 resolved := c.resolveDeclaredMembers(source)
@@ -19648,76 +19623,34 @@ func (c *Checker) prepareLazyMembers(t *Type, lm *lazyMemberTable) {
1964819623 }
1964919624 }
1965019625 slices.Sort(lm.unaffected)
19651- lm.callSignatures = c.instantiateSignatures(resolved.declaredCallSignatures, lm.mapper)
19652- lm.constructSignatures = c.instantiateSignatures(resolved.declaredConstructSignatures, lm.mapper)
19653- lm.indexInfos = c.instantiateIndexInfos(resolved.declaredIndexInfos, lm.mapper)
19654- baseTypes := c.getBaseTypes(source)
19655- lm.state = lazyMembersResolvingBases
19656- if t.objectFlags&ObjectFlagsMembersResolved != 0 {
19657- // A lookup led to t being resolved in full; resolveObjectTypeMembers
19658- // would now go on to replace those members with its own.
19659- c.resolveLazyMembers(t, lm)
19660- }
19661- callSignatures, constructSignatures, indexInfos := lm.callSignatures, lm.constructSignatures, lm.indexInfos
19626+ callSignatures := c.instantiateSignatures(resolved.declaredCallSignatures, lm.mapper)
19627+ constructSignatures := c.instantiateSignatures(resolved.declaredConstructSignatures, lm.mapper)
19628+ indexInfos := c.instantiateIndexInfos(resolved.declaredIndexInfos, lm.mapper)
1966219629 thisArgument := core.LastOrNil(lm.typeArguments)
19663- for _, baseType := range baseTypes {
19630+ for _, baseType := range c.getBaseTypes(source) {
1966419631 instantiatedBaseType := baseType
1966519632 if thisArgument != nil {
1966619633 instantiatedBaseType = c.getTypeWithThisArgument(c.instantiateType(baseType, lm.mapper), thisArgument, false /*needsApparentType*/)
1966719634 }
1966819635 lm.baseTypes = append(lm.baseTypes, instantiatedBaseType)
19669- if lm.state == lazyMembersResolvingBases && !c.prepareBaseTypeMembers(instantiatedBaseType) {
19670- // The base type's members are only partially resolved, and t must
19671- // inherit them as they are now.
19672- c.resolveLazyMembers(t, lm)
19673- }
19674- if lm.state == lazyMembersMaterialized {
19675- lm.members = c.addInheritedMembers(lm.members, c.getPropertiesOfType(instantiatedBaseType))
19636+ if c.getReadyLazyMemberTable(c.getReducedApparentType(instantiatedBaseType)) == nil {
19637+ c.getPropertiesOfType(instantiatedBaseType)
1967619638 }
1967719639 callSignatures, constructSignatures, indexInfos = c.appendInheritedSignaturesAndIndexInfos(callSignatures, constructSignatures, indexInfos, instantiatedBaseType)
19678- lm.inheritedCount++
1967919640 }
1968019641 lm.callSignatures, lm.constructSignatures, lm.indexInfos = callSignatures, constructSignatures, indexInfos
19681- if lm.state == lazyMembersMaterialized {
19682- t.objectFlags &^= ObjectFlagsUnresolvedMembers
19683- c.setStructuredTypeMembers(t, lm.members, callSignatures, constructSignatures, indexInfos)
19684- delete(c.lazyMemberTables, t)
19685- return
19686- }
19687- lm.state = lazyMembersReady
19688- }
19689-
19690- // prepareBaseTypeMembers resolves the members of an instantiated base type as
19691- // inheriting from it in resolveObjectTypeMembers would. It returns false, and
19692- // leaves that to the caller, when those members are only partially resolved.
19693- func (c *Checker) prepareBaseTypeMembers(baseType *Type) bool {
19694- if baseType == c.anyType {
19695- return true
19696- }
19697- reduced := c.getReducedApparentType(baseType)
19698- if reduced.flags&TypeFlagsObject != 0 {
19699- if reduced.objectFlags&ObjectFlagsUnresolvedMembers != 0 {
19700- return false
19701- }
19702- if lm := c.getLazyMemberTable(reduced); lm != nil {
19703- return lm.state == lazyMembersReady
19704- }
19642+ lm.ready = true
19643+ if t.objectFlags&ObjectFlagsMembersResolved != 0 {
19644+ // Preparing the table led to t being resolved in full, and
19645+ // resolveObjectTypeMembers would now replace those members.
19646+ c.resolveLazyMembers(t, lm)
1970519647 }
19706- c.getPropertiesOfType(baseType)
19707- c.getSignaturesOfType(baseType, SignatureKindCall)
19708- c.getSignaturesOfType(baseType, SignatureKindConstruct)
19709- c.getIndexInfosOfType(baseType)
19710- return true
1971119648}
1971219649
19713- // resolveLazyMembers resolves the members of t, whose lazy member table was
19714- // prepared, as resolveObjectTypeMembers does. While the table's base types are
19715- // still being prepared, it only exposes the members inherited so far, like
19716- // resolveObjectTypeMembers would at that point, and prepareLazyMembers
19717- // finishes the job.
19650+ // resolveLazyMembers resolves the members of t from its lazy member table, as
19651+ // resolveObjectTypeMembers does.
1971819652func (c *Checker) resolveLazyMembers(t *Type, lm *lazyMemberTable) {
19719- source := t.Target()
19720- resolved := c.resolveDeclaredMembers(source)
19653+ resolved := c.resolveDeclaredMembers(t.Target())
1972119654 var members ast.SymbolTable
1972219655 if len(resolved.declaredMembers) != 0 {
1972319656 members = make(ast.SymbolTable, len(resolved.declaredMembers))
@@ -19727,19 +19660,9 @@ func (c *Checker) resolveLazyMembers(t *Type, lm *lazyMemberTable) {
1972719660 }
1972819661 }
1972919662 }
19730- if len(c.getBaseTypes(source)) != 0 {
19731- c.setStructuredTypeMembers(t, members, lm.callSignatures, lm.constructSignatures, lm.indexInfos)
19732- t.objectFlags |= ObjectFlagsUnresolvedMembers
19733- for _, baseType := range lm.baseTypes[:lm.inheritedCount] {
19734- members = c.addInheritedMembers(members, c.getPropertiesOfType(baseType))
19735- }
19736- }
19737- if lm.state != lazyMembersReady {
19738- lm.state = lazyMembersMaterialized
19739- lm.members = members
19740- return
19663+ for _, baseType := range lm.baseTypes {
19664+ members = c.addInheritedMembers(members, c.getPropertiesOfType(baseType))
1974119665 }
19742- t.objectFlags &^= ObjectFlagsUnresolvedMembers
1974319666 c.setStructuredTypeMembers(t, members, lm.callSignatures, lm.constructSignatures, lm.indexInfos)
1974419667 delete(c.lazyMemberTables, t)
1974519668}
@@ -19778,52 +19701,36 @@ func (c *Checker) getMemberOfStructuredType(t *Type, name string) *ast.Symbol {
1977819701}
1977919702
1978019703func (c *Checker) getMemberOfUnresolvedStructuredType(t *Type, name string) *ast.Symbol {
19781- if symbol, ok := c.lookupMemberLazily(t, name); ok {
19782- return symbol
19704+ if !isReservedMemberName(name) {
19705+ if lm := c.getReadyLazyMemberTable(t); lm != nil {
19706+ return c.lookupLazyMember(t, lm, name)
19707+ }
1978319708 }
1978419709 return c.resolveStructuredTypeMembers(t).members[name]
1978519710}
1978619711
19787- // lookupMemberLazily returns what resolveStructuredTypeMembers(t).members[name]
19788- // would hold, without building t's member table. ok is false when the lazy
19789- // path can't answer and the caller must resolve members normally.
19790- func (c *Checker) lookupMemberLazily(t *Type, name string) (symbol *ast.Symbol, ok bool) {
19791- if isReservedMemberName(name) {
19792- return nil, false
19793- }
19794- lm := c.getLazyMemberTable(t)
19795- if lm == nil || lm.state == lazyMembersResolvingDeclared {
19796- return nil, false
19797- }
19712+ // lookupLazyMember returns what resolveStructuredTypeMembers(t).members[name]
19713+ // would hold: the declared member, or else the property inherited from the
19714+ // first base type that has one, where a base may only fill a missing or
19715+ // non-value entry (addInheritedMembers).
19716+ func (c *Checker) lookupLazyMember(t *Type, lm *lazyMemberTable, name string) *ast.Symbol {
1979819717 if symbol, ok := lm.found[name]; ok {
19799- return symbol, true
19718+ return symbol
1980019719 }
19801- // Mirrors resolveObjectTypeMembers: declared named members first, then
19802- // inherited properties, where a base may only fill a missing or non-value
19803- // entry (addInheritedMembers).
19804- resolved := c.resolveDeclaredMembers(t.Target())
1980519720 var result *ast.Symbol
19806- if decl := resolved .declaredMembers[name]; decl != nil && c.isNamedMember(decl, name) {
19721+ if decl := c.resolveDeclaredMembers(t.Target()) .declaredMembers[name]; decl != nil && c.isNamedMember(decl, name) {
1980719722 result = c.getLazyDeclaredMember(lm, decl, name)
1980819723 }
19809- baseTypes := lm.baseTypes[:lm.inheritedCount]
19810- if lm.state != lazyMembersReady && len(resolved.declaredMembers) == 0 {
19811- // While base types are being resolved, resolveObjectTypeMembers only
19812- // exposes inherited members through the table of declared members.
19813- baseTypes = nil
19814- }
19815- for _, baseType := range baseTypes {
19724+ for _, baseType := range lm.baseTypes {
1981619725 if result != nil && result.Flags&ast.SymbolFlagsValue != 0 {
1981719726 break
1981819727 }
1981919728 if prop := c.getNamedPropertyOfType(baseType, name); prop != nil && isInheritableProperty(prop) {
1982019729 result = prop
1982119730 }
1982219731 }
19823- if lm.state == lazyMembersReady {
19824- lm.found[name] = result
19825- }
19826- return result, true
19732+ lm.found[name] = result
19733+ return result
1982719734}
1982819735
1982919736// getNamedPropertyOfType finds name among getPropertiesOfType(t).
0 commit comments