Repository navigation
Lazy member resolution for class and interface types - #64915
Conversation
|
TypeScript Bot (@typescript-bot) test it |
|
TypeScript Bot (@typescript-bot) test it |
There was a problem hiding this comment.
🟡 Changes recommended
The layout-cache key can conflate base instantiations with different inherited members, causing missing properties and nil property slots.
1 open issue
What changed in this PR
This PR reduces eager member instantiation in the native TypeScript checker by sharing class and interface member layouts and resolving properties on demand.
Changes:
- Adds cached member layouts and per-type lazy property resolution.
- Updates checker and language-service consumers to use lazy-aware accessors.
- Adjusts a diagnostic baseline for the changed property ordering.
| File | Description |
|---|---|
tsc/testdata/baselines/reference/conformance/arityAndOrderCompatibility01.errors.txt |
Updates which incompatible properties diagnostics report. |
tsc/internal/checker/types.go |
Adds member layouts, lazy state, and property accessors. |
tsc/internal/checker/services.go |
Uses lazy-aware member enumeration for modules. |
tsc/internal/checker/relater.go |
Uses layout metadata during structural comparisons. |
tsc/internal/checker/nodebuilderimpl.go |
Resolves lazy members when building type nodes. |
tsc/internal/checker/nodebuilder_hover.go |
Resolves properties before filtering inherited hover members. |
tsc/internal/checker/checker.go |
Creates and caches layouts and integrates lazy lookups. |
Review effort: Balanced
| if baseType.objectFlags&ObjectFlagsReference != 0 { | ||
| b.writeType(c.getTargetType(baseType)) |
|
TypeScript Bot (@typescript-bot) perf test this faster |
|
Hey Anders Hejlsberg (@ahejlsberg), the results of running the DT tests are ready. Everything looks the same! |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the user tests with tsc comparing Everything looks good! |
|
Jake Bailey (@jakebailey), the perf run you requested failed. You can check the log here. |
|
Failure was due to: |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the top 400 repos with tsc comparing Something interesting changed - please have a look. Details
|
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
TypeScript Bot (@typescript-bot) perf test this faster |
|
Jake Bailey (@jakebailey) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (t *StructuredType) getProperties() []*ast.Symbol { | ||
| if lazy := t.getLazyState(); lazy != nil && !lazy.propertiesResolved { | ||
| for i := range lazy.layout.memberInfos { | ||
| t.getPropertyAt(i) |
There was a problem hiding this comment.
Are we paying a little bit of extra overhead for the initial checks of getPropertyAt? Maybe it would make sense to extract the part of getPropertyAt to getPropertyAtWorker that takes the *LazyState, the properties, and current index.
There was a problem hiding this comment.
I think the effect is so minimal it isn't worth it.
| if memberInfoMap == nil { | ||
| memberInfoMap = make(map[string]*MemberInfo) | ||
| } | ||
| memberInfoMap[symbol.Name()] = &MemberInfo{symbol: symbol, baseIndex: int32(baseIndex)} |
There was a problem hiding this comment.
I think we can avoid the per-member allocations by collecting into a map[string]MemberInfo first, then allocating the records together:
storage := make([]MemberInfo, len(members))
memberInfoMap := make(map[string]*MemberInfo, len(members))
memberInfos := make([]*MemberInfo, len(members))
i := 0
for name, info := range members {
storage[i] = info
memberInfoMap[name] = &storage[i]
memberInfos[i] = &storage[i]
i++
}| } | ||
| } | ||
| } | ||
| memberInfos := slices.Collect(maps.Values(memberInfoMap)) |
There was a problem hiding this comment.
Preallocate the slice:
memberInfos := slices.AppendSeq(make([]*MemberInfo, 0, len(memberInfoMap)), maps.Values(memberInfoMap))|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the top 400 repos with tsc comparing Everything looks good! |
|
Latest commit uses layout properties to compute |
|
TypeScript Bot (@typescript-bot) test it |
|
Hey Anders Hejlsberg (@ahejlsberg), the results of running the DT tests are ready. Everything looks the same! |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the user tests with tsc comparing Everything looks good! |
|
Anders Hejlsberg (@ahejlsberg) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
TypeScript Bot (@typescript-bot) perf test this faster |
|
Ok, I think this one is good to go now. |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the top 400 repos with tsc comparing Everything looks good! |
|
Anders Hejlsberg (@ahejlsberg) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
TypeScript Bot (@typescript-bot) test it |
|
Hey Anders Hejlsberg (@ahejlsberg), the results of running the DT tests are ready. Everything looks the same! |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the user tests with tsc comparing Everything looks good! |
|
Anders Hejlsberg (@ahejlsberg) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the top 400 repos with tsc comparing Everything looks good! |

Inspired by #64765, this PR implements lazy member resolution for class and interface types. The PR computes shared member layouts for classes and interfaces and uses these layouts to lazily populate the properties of type instances.
The single baseline change is due to an improvement in member sorting that causes the numerically named members and the
lengthmember of tuple types to be sorted before those members that are inherited fromArray<T>.