Skip to content

Commit f7aaf7e

Browse files
committed
MandatoryPerformanceOptimizations: handle all kind of witness-table entries when specializing witness-tables
Support associated-type and associated-conformance entries. This enable existentials with associated types.
1 parent c05234e commit f7aaf7e

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ func specializeWitnessTable(forConformance conformance: Conformance,
8989

9090
let newEntries = witnessTable.entries.map { origEntry in
9191
switch origEntry {
92+
case .invalid:
93+
return WitnessTable.Entry.invalid
9294
case .method(let requirement, let witness):
9395
guard let origMethod = witness else {
9496
return origEntry
@@ -108,9 +110,14 @@ func specializeWitnessTable(forConformance conformance: Conformance,
108110
substitutions: conformance.specializedSubstitutions)
109111
specializeWitnessTable(forConformance: baseConf, errorLocation: errorLocation, context, notifyNewWitnessTable)
110112
return .baseProtocol(requirement: requirement, witness: baseConf)
111-
default:
112-
// TODO: handle other witness table entry kinds
113-
fatalError("unsupported witness table etnry")
113+
case .associatedType(let requirement, let witness):
114+
let substType = witness.subst(with: conformance.specializedSubstitutions)
115+
return .associatedType(requirement: requirement, witness: substType)
116+
case .associatedConformance(let requirement, let proto, let witness):
117+
if witness.isSpecialized {
118+
specializeWitnessTable(forConformance: witness, errorLocation: errorLocation, context, notifyNewWitnessTable)
119+
}
120+
return .associatedConformance(requirement: requirement, protocol: proto, witness: witness)
114121
}
115122
}
116123
let newWT = context.createWitnessTable(entries: newEntries,conformance: conformance,

test/embedded/existential-class-bound1.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,61 @@ func test(existential: any ClassBound) {
2929
existential.bar()
3030
}
3131

32+
public protocol ProtoWithAssocType<T>: AnyObject {
33+
associatedtype T
34+
func foo(t: T)
35+
}
36+
37+
final public class GenClass<T: BinaryInteger>: ProtoWithAssocType {
38+
public func foo(t: T) {
39+
print(t)
40+
}
41+
}
42+
43+
public func createExWithAssocType() -> any ProtoWithAssocType<Int> {
44+
return GenClass<Int>()
45+
}
46+
47+
public func callExWithAssocType(_ p: any ProtoWithAssocType<Int>) {
48+
p.foo(t: 27)
49+
}
50+
51+
public protocol Q: AnyObject {
52+
func bar()
53+
}
54+
55+
public protocol ProtoWithAssocConf: AnyObject {
56+
associatedtype A: Q
57+
func foo() -> A
58+
}
59+
60+
public class GenClass2<T>: Q {
61+
var t: T
62+
63+
init(t : T) { self.t = t }
64+
65+
public func bar() {
66+
print("bar")
67+
}
68+
}
69+
70+
final public class GenClass3<V>: ProtoWithAssocConf {
71+
public func foo() -> GenClass2<Int> {
72+
print("foo")
73+
return GenClass2(t: 27)
74+
}
75+
}
76+
77+
78+
public func createExWithAssocConf() -> any ProtoWithAssocConf {
79+
return GenClass3<Int>()
80+
}
81+
82+
public func callExWithAssocConf(_ p: any ProtoWithAssocConf) {
83+
let x = p.foo()
84+
x.bar()
85+
}
86+
3287
@main
3388
struct Main {
3489
static func main() {
@@ -38,6 +93,11 @@ struct Main {
3893
test(existential: MyOtherClass())
3994
// CHECK: MyOtherClass.foo()
4095
// CHECK: MyOtherClass.bar()
96+
callExWithAssocType(createExWithAssocType())
97+
// CHECK: 27
98+
callExWithAssocConf(createExWithAssocConf())
99+
// CHECK: foo
100+
// CHECK: bar
41101
}
42102
}
43103

0 commit comments

Comments
 (0)