Skip to content

Commit e1930e0

Browse files
authored
Merge branch 'main' into fix/64231
2 parents 9fb9005 + 8d9b6da commit e1930e0

31 files changed

Lines changed: 1562 additions & 88 deletions

‎tsc/internal/checker/checker.go‎

Lines changed: 191 additions & 65 deletions
Large diffs are not rendered by default.

‎tsc/internal/checker/nodebuilder_hover.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ func (b *NodeBuilderImpl) expandInterfaceDecl(symbol *ast.Symbol) *ast.Node {
263263
members = append(members, b.signatureToSignatureDeclarationHelper(sig, ast.KindCallSignature, nil))
264264
}
265265
// Properties, filtering inherited
266-
filteredProps := b.filterInheritedProperties(interfaceType, baseTypes, resolved.properties)
266+
filteredProps := b.filterInheritedProperties(interfaceType, baseTypes, resolved.getProperties())
267267
members = b.serializePropertiesWithTruncation(filteredProps, members)
268268

269269
// Heritage clauses

‎tsc/internal/checker/nodebuilderimpl.go‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ func (b *NodeBuilderImpl) getResolvedTypeWithoutAbstractConstructSignatures(t *S
576576
t.extra.objectTypeWithoutAbstractConstructSignatures = t.AsType()
577577
return t.AsType()
578578
}
579-
typeCopy := b.ch.newAnonymousType(t.symbol, t.members, t.CallSignatures(), core.IfElse(len(constructSignatures) > 0, constructSignatures, []*Signature{}), t.getIndexInfos())
579+
typeCopy := b.ch.newAnonymousType(t.symbol, t.getMembers(), t.CallSignatures(), core.IfElse(len(constructSignatures) > 0, constructSignatures, []*Signature{}), t.getIndexInfos())
580580
t.extra.objectTypeWithoutAbstractConstructSignatures = typeCopy
581581
typeCopy.AsStructuredType().ensureExtra().objectTypeWithoutAbstractConstructSignatures = typeCopy
582582
return typeCopy
@@ -2758,7 +2758,7 @@ func (b *NodeBuilderImpl) createTypeNodesFromResolvedType(resolvedType *Structur
27582758
typeElements = slices.Concat(typeElements, b.indexInfoToObjectComputedNamesOrSignatureDeclaration(info, typeNode))
27592759
}
27602760

2761-
properties := resolvedType.properties
2761+
properties := resolvedType.getProperties()
27622762
if len(properties) == 0 {
27632763
return b.f.NewNodeList(typeElements)
27642764
}
@@ -2807,7 +2807,7 @@ func (b *NodeBuilderImpl) createTypeNodeFromObjectType(t *Type) *ast.TypeNode {
28072807
resolved := b.ch.resolveStructuredTypeMembers(t)
28082808
callSigs := resolved.CallSignatures()
28092809
ctorSigs := resolved.ConstructSignatures()
2810-
if len(resolved.properties) == 0 && len(resolved.getIndexInfos()) == 0 {
2810+
if len(resolved.getProperties()) == 0 && len(resolved.getIndexInfos()) == 0 {
28112811
if len(callSigs) == 0 && len(ctorSigs) == 0 {
28122812
b.ctx.approximateLength += 2
28132813
result := b.f.NewTypeLiteralNode(b.f.NewNodeList([]*ast.Node{}))
@@ -2836,9 +2836,9 @@ func (b *NodeBuilderImpl) createTypeNodeFromObjectType(t *Type) *ast.TypeNode {
28362836
return b.ch.getOrCreateTypeFromSignature(s)
28372837
})
28382838
// count the number of type elements excluding abstract constructors
2839-
typeElementCount := len(callSigs) + (len(ctorSigs) - len(abstractSignatures)) + len(resolved.getIndexInfos()) + core.IfElse(b.ctx.flags&nodebuilder.FlagsWriteClassExpressionAsTypeLiteral != 0, core.CountWhere(resolved.properties, func(p *ast.Symbol) bool {
2839+
typeElementCount := len(callSigs) + (len(ctorSigs) - len(abstractSignatures)) + len(resolved.getIndexInfos()) + core.IfElse(b.ctx.flags&nodebuilder.FlagsWriteClassExpressionAsTypeLiteral != 0, core.CountWhere(resolved.getProperties(), func(p *ast.Symbol) bool {
28402840
return p.Flags()&ast.SymbolFlagsPrototype == 0
2841-
}), len(resolved.properties))
2841+
}), len(resolved.getProperties()))
28422842
// don't include an empty object literal if there were no other static-side
28432843
// properties to write, i.e. `abstract class C { }` becomes `abstract new () => {}`
28442844
// and not `(abstract new () => {}) & {}`

‎tsc/internal/checker/relater.go‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ func (c *Checker) elaborateArrowFunction(node *ast.Node, source *Type, target *T
679679
func (c *Checker) isWeakType(t *Type) bool {
680680
if t.flags&TypeFlagsObject != 0 {
681681
resolved := c.resolveStructuredTypeMembers(t)
682-
return len(resolved.getSignatures()) == 0 && len(resolved.getIndexInfos()) == 0 && len(resolved.properties) > 0 && core.Every(resolved.properties, func(p *ast.Symbol) bool {
682+
return len(resolved.getSignatures()) == 0 && len(resolved.getIndexInfos()) == 0 && len(c.getLayoutPropertiesOfType(t)) > 0 && core.Every(c.getLayoutPropertiesOfType(t), func(p *ast.Symbol) bool {
683683
return p.Flags()&ast.SymbolFlagsOptional != 0
684684
})
685685
}
@@ -975,14 +975,16 @@ func (c *Checker) getUnmatchedProperties(source *Type, target *Type, requireOpti
975975
}
976976

977977
func (c *Checker) getUnmatchedPropertiesWorker(source *Type, target *Type, requireOptionalProperties bool, matchDiscriminantProperties bool, propsOut *[]*ast.Symbol) *ast.Symbol {
978-
properties := c.getPropertiesOfType(target)
979-
for _, targetProp := range properties {
978+
for _, targetProp := range c.getLayoutPropertiesOfType(target) {
980979
// TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass
981980
if isStaticPrivateIdentifierProperty(targetProp) {
982981
continue
983982
}
984983
if requireOptionalProperties || targetProp.Flags()&ast.SymbolFlagsOptional == 0 && targetProp.CheckFlags()&ast.CheckFlagsPartial == 0 {
985984
sourceProp := c.getPropertyOfType(source, targetProp.Name())
985+
if sourceProp == nil || matchDiscriminantProperties {
986+
targetProp = c.getPropertyOfType(target, targetProp.Name())
987+
}
986988
if sourceProp == nil {
987989
if propsOut == nil {
988990
return targetProp

‎tsc/internal/checker/services.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb
154154
if reducedType.flags&TypeFlagsStructuredType == 0 {
155155
return
156156
}
157-
for name, symbol := range c.resolveStructuredTypeMembers(reducedType).members {
157+
for name, symbol := range c.resolveStructuredTypeMembers(reducedType).getMembers() {
158158
if c.isNamedMember(symbol, name) {
159159
cb(symbol, name)
160160
}

‎tsc/internal/checker/types.go‎

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,82 @@ func (t *StructuredType) ConstructSignatures() []*Signature {
11431143
return slices.Clip(t.extra.signatures[t.extra.callSignatureCount:])
11441144
}
11451145

1146+
func (t *StructuredType) getMember(name string) *ast.Symbol {
1147+
if t.members != nil {
1148+
return t.members[name]
1149+
}
1150+
lazy := t.getLazyState()
1151+
if lazy == nil {
1152+
return nil
1153+
}
1154+
memberInfo := lazy.layout.memberInfoMap[name]
1155+
if memberInfo == nil {
1156+
return nil
1157+
}
1158+
return t.getPropertyAt(int(memberInfo.slotIndex))
1159+
}
1160+
1161+
func (t *StructuredType) getMembers() ast.SymbolTable {
1162+
if t.members == nil {
1163+
if properties := t.getProperties(); len(properties) != 0 {
1164+
t.members = make(ast.SymbolTable, len(properties))
1165+
for _, member := range properties {
1166+
t.members[member.Name()] = member
1167+
}
1168+
}
1169+
}
1170+
return t.members
1171+
}
1172+
1173+
func (t *StructuredType) getPropertyAt(index int) *ast.Symbol {
1174+
lazy := t.getLazyState()
1175+
if lazy == nil {
1176+
return t.properties[index]
1177+
}
1178+
if t.properties == nil {
1179+
t.properties = make([]*ast.Symbol, len(lazy.layout.memberInfos))
1180+
}
1181+
member := t.properties[index]
1182+
if member == nil {
1183+
memberInfo := lazy.layout.memberInfos[index]
1184+
if memberInfo.baseIndex < 0 {
1185+
member = t.checker.instantiateSymbol(memberInfo.symbol, lazy.mapper)
1186+
} else {
1187+
member = t.checker.getPropertyOfType(lazy.baseTypes[memberInfo.baseIndex], memberInfo.symbol.Name())
1188+
}
1189+
t.properties[index] = member
1190+
}
1191+
return member
1192+
}
1193+
1194+
func (t *StructuredType) getProperties() []*ast.Symbol {
1195+
if lazy := t.getLazyState(); lazy != nil && !lazy.propertiesResolved {
1196+
for i := range lazy.layout.memberInfos {
1197+
t.getPropertyAt(i)
1198+
}
1199+
lazy.propertiesResolved = true
1200+
}
1201+
return t.AsStructuredType().properties
1202+
}
1203+
1204+
func (t *StructuredType) hasProperties() bool {
1205+
if len(t.properties) != 0 {
1206+
return true
1207+
}
1208+
lazy := t.getLazyState()
1209+
if lazy == nil {
1210+
return false
1211+
}
1212+
return len(lazy.layout.memberInfos) != 0
1213+
}
1214+
1215+
func (t *StructuredType) getLazyState() *LazyState {
1216+
if t.objectFlags&(ObjectFlagsClassOrInterface|ObjectFlagsReference) != 0 {
1217+
return t.AsType().AsTypeReference().lazy
1218+
}
1219+
return nil
1220+
}
1221+
11461222
func (t *StructuredType) getSignatures() []*Signature {
11471223
if t.extra == nil {
11481224
return nil
@@ -1165,7 +1241,7 @@ func (t *StructuredType) ensureExtra() *structuredTypeExtra {
11651241
}
11661242

11671243
func (t *StructuredType) Properties() []*ast.Symbol {
1168-
return t.properties
1244+
return t.getProperties()
11691245
}
11701246

11711247
// Except for tuple type references and reverse mapped types, all object types have an associated symbol.
@@ -1216,6 +1292,27 @@ type TypeReference struct {
12161292
ObjectType
12171293
node *ast.Node // TypeReferenceNode | ArrayTypeNode | TupleTypeNode when deferred, else nil
12181294
resolvedTypeArguments []*Type
1295+
lazy *LazyState // Resolved member layout and instantiation state
1296+
}
1297+
1298+
type LazyState struct {
1299+
layout *MemberLayout
1300+
mapper *TypeMapper
1301+
baseTypes []*Type
1302+
propertiesResolved bool
1303+
}
1304+
1305+
type MemberLayout struct {
1306+
id uint32 // Unique identifier for the member layout
1307+
memberInfoMap map[string]*MemberInfo // MemberInfos keyed by property name
1308+
memberInfos []MemberInfo // MemberInfos in sorted order
1309+
layoutProperties []*ast.Symbol // Lazily created list of layout properties (symbols corresponding to memberInfos)
1310+
}
1311+
1312+
type MemberInfo struct {
1313+
symbol *ast.Symbol // Uninstantiated symbol
1314+
baseIndex int32 // Index of base type with symbol, or -1 if locally declared
1315+
slotIndex int32 // Index of resolved symbol in members array
12191316
}
12201317

12211318
func (t *TypeReference) AsTypeReference() *TypeReference { return t }
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//// [tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts] ////
2+
3+
//// [lateBoundMemberLayoutReentrancy.ts]
4+
declare const rI: RI<"a">;
5+
rI.x
6+
interface RI<T extends "a" | "b"> {
7+
x: T;
8+
[rI.x]: "b";
9+
}
10+
declare const rI2: RI<"b">;
11+
export const v1 = rI2.a;
12+
export const v2 = rI.a;
13+
export type K2 = keyof RI<"b">;
14+
export const k: K2 = "a";
15+
export const o: RI<"b"> = { x: "b", a: "b" };
16+
17+
declare const rC: RC<"a">;
18+
rC.x
19+
declare class RC<T extends "a" | "b"> {
20+
x: T;
21+
[rC.x]: "b";
22+
}
23+
declare const rC2: RC<"b">;
24+
export const w1 = rC2.a;
25+
export const w2 = rC.a;
26+
27+
28+
//// [lateBoundMemberLayoutReentrancy.js]
29+
rI.x;
30+
export const v1 = rI2.a;
31+
export const v2 = rI.a;
32+
export const k = "a";
33+
export const o = { x: "b", a: "b" };
34+
rC.x;
35+
export const w1 = rC2.a;
36+
export const w2 = rC.a;
37+
38+
39+
//// [lateBoundMemberLayoutReentrancy.d.ts]
40+
declare const rI: RI<"a">;
41+
interface RI<T extends "a" | "b"> {
42+
x: T;
43+
[rI.x]: "b";
44+
}
45+
export declare const v1: "b";
46+
export declare const v2: "b";
47+
export type K2 = keyof RI<"b">;
48+
export declare const k: K2;
49+
export declare const o: RI<"b">;
50+
export declare const w1: "b";
51+
export declare const w2: "b";
52+
export {};
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//// [tests/cases/compiler/lateBoundMemberLayoutReentrancy.ts] ////
2+
3+
=== lateBoundMemberLayoutReentrancy.ts ===
4+
declare const rI: RI<"a">;
5+
>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13))
6+
>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4))
7+
8+
rI.x
9+
>rI.x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35))
10+
>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13))
11+
>x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35))
12+
13+
interface RI<T extends "a" | "b"> {
14+
>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4))
15+
>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 13))
16+
17+
x: T;
18+
>x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35))
19+
>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 13))
20+
21+
[rI.x]: "b";
22+
>[rI.x] : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9))
23+
>rI.x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35))
24+
>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13))
25+
>x : Symbol(RI.x, Decl(lateBoundMemberLayoutReentrancy.ts, 2, 35))
26+
}
27+
declare const rI2: RI<"b">;
28+
>rI2 : Symbol(rI2, Decl(lateBoundMemberLayoutReentrancy.ts, 6, 13))
29+
>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4))
30+
31+
export const v1 = rI2.a;
32+
>v1 : Symbol(v1, Decl(lateBoundMemberLayoutReentrancy.ts, 7, 12))
33+
>rI2.a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9))
34+
>rI2 : Symbol(rI2, Decl(lateBoundMemberLayoutReentrancy.ts, 6, 13))
35+
>a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9))
36+
37+
export const v2 = rI.a;
38+
>v2 : Symbol(v2, Decl(lateBoundMemberLayoutReentrancy.ts, 8, 12))
39+
>rI.a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9))
40+
>rI : Symbol(rI, Decl(lateBoundMemberLayoutReentrancy.ts, 0, 13))
41+
>a : Symbol(RI[rI.x], Decl(lateBoundMemberLayoutReentrancy.ts, 3, 9))
42+
43+
export type K2 = keyof RI<"b">;
44+
>K2 : Symbol(K2, Decl(lateBoundMemberLayoutReentrancy.ts, 8, 23))
45+
>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4))
46+
47+
export const k: K2 = "a";
48+
>k : Symbol(k, Decl(lateBoundMemberLayoutReentrancy.ts, 10, 12))
49+
>K2 : Symbol(K2, Decl(lateBoundMemberLayoutReentrancy.ts, 8, 23))
50+
51+
export const o: RI<"b"> = { x: "b", a: "b" };
52+
>o : Symbol(o, Decl(lateBoundMemberLayoutReentrancy.ts, 11, 12))
53+
>RI : Symbol(RI, Decl(lateBoundMemberLayoutReentrancy.ts, 1, 4))
54+
>x : Symbol(x, Decl(lateBoundMemberLayoutReentrancy.ts, 11, 27))
55+
>a : Symbol(a, Decl(lateBoundMemberLayoutReentrancy.ts, 11, 35))
56+
57+
declare const rC: RC<"a">;
58+
>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13))
59+
>RC : Symbol(RC, Decl(lateBoundMemberLayoutReentrancy.ts, 14, 4))
60+
61+
rC.x
62+
>rC.x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39))
63+
>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13))
64+
>x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39))
65+
66+
declare class RC<T extends "a" | "b"> {
67+
>RC : Symbol(RC, Decl(lateBoundMemberLayoutReentrancy.ts, 14, 4))
68+
>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 17))
69+
70+
x: T;
71+
>x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39))
72+
>T : Symbol(T, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 17))
73+
74+
[rC.x]: "b";
75+
>[rC.x] : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9))
76+
>rC.x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39))
77+
>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13))
78+
>x : Symbol(RC.x, Decl(lateBoundMemberLayoutReentrancy.ts, 15, 39))
79+
}
80+
declare const rC2: RC<"b">;
81+
>rC2 : Symbol(rC2, Decl(lateBoundMemberLayoutReentrancy.ts, 19, 13))
82+
>RC : Symbol(RC, Decl(lateBoundMemberLayoutReentrancy.ts, 14, 4))
83+
84+
export const w1 = rC2.a;
85+
>w1 : Symbol(w1, Decl(lateBoundMemberLayoutReentrancy.ts, 20, 12))
86+
>rC2.a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9))
87+
>rC2 : Symbol(rC2, Decl(lateBoundMemberLayoutReentrancy.ts, 19, 13))
88+
>a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9))
89+
90+
export const w2 = rC.a;
91+
>w2 : Symbol(w2, Decl(lateBoundMemberLayoutReentrancy.ts, 21, 12))
92+
>rC.a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9))
93+
>rC : Symbol(rC, Decl(lateBoundMemberLayoutReentrancy.ts, 13, 13))
94+
>a : Symbol(RC[rC.x], Decl(lateBoundMemberLayoutReentrancy.ts, 16, 9))
95+

0 commit comments

Comments
 (0)