Skip to content

Commit f769080

Browse files
committed
Embedded: support existentials with inherited conformances
That means: derived classes where the base conforms to a protocol
1 parent 54e7cdd commit f769080

File tree

6 files changed

+69
-4
lines changed

6 files changed

+69
-4
lines changed

SwiftCompilerSources/Sources/AST/Conformance.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ public struct Conformance: CustomStringConvertible, NoReflectionChildren {
4747
return bridged.getGenericConformance().conformance
4848
}
4949

50+
public var isInherited: Bool {
51+
assert(isConcrete)
52+
return bridged.isInheritedConformance()
53+
}
54+
55+
public var inheritedConformance: Conformance {
56+
assert(isInherited)
57+
return bridged.getInheritedConformance().conformance
58+
}
59+
5060
public var specializedSubstitutions: SubstitutionMap {
5161
assert(isSpecialized)
5262
return SubstitutionMap(bridged: bridged.getSpecializedSubstitutions())

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,8 @@ private func shouldInline(apply: FullApplySite, callee: Function, alreadyInlined
271271
private func specializeWitnessTables(for initExRef: InitExistentialRefInst, _ context: ModulePassContext,
272272
_ worklist: inout FunctionWorklist)
273273
{
274-
for conformance in initExRef.conformances where conformance.isConcrete {
274+
for c in initExRef.conformances where c.isConcrete {
275+
let conformance = c.isInherited ? c.inheritedConformance : c
275276
let origWitnessTable = context.lookupWitnessTable(for: conformance)
276277
if conformance.isSpecialized {
277278
if origWitnessTable == nil {

include/swift/AST/ASTBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,8 +2042,10 @@ struct BridgedConformance {
20422042
BRIDGED_INLINE bool isConcrete() const;
20432043
BRIDGED_INLINE bool isValid() const;
20442044
BRIDGED_INLINE bool isSpecializedConformance() const;
2045+
BRIDGED_INLINE bool isInheritedConformance() const;
20452046
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getType() const;
20462047
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getGenericConformance() const;
2048+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getInheritedConformance() const;
20472049
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getSpecializedSubstitutions() const;
20482050
};
20492051

include/swift/AST/ASTBridgingImpl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ bool BridgedConformance::isSpecializedConformance() const {
163163
return swift::isa<swift::SpecializedProtocolConformance>(unbridged().getConcrete());
164164
}
165165

166+
bool BridgedConformance::isInheritedConformance() const {
167+
return swift::isa<swift::InheritedProtocolConformance>(unbridged().getConcrete());
168+
}
169+
166170
BridgedASTType BridgedConformance::getType() const {
167171
return {unbridged().getConcrete()->getType().getPointer()};
168172
}
@@ -172,6 +176,11 @@ BridgedConformance BridgedConformance::getGenericConformance() const {
172176
return {swift::ProtocolConformanceRef(specPC->getGenericConformance())};
173177
}
174178

179+
BridgedConformance BridgedConformance::getInheritedConformance() const {
180+
auto *inheritedConf = swift::cast<swift::InheritedProtocolConformance>(unbridged().getConcrete());
181+
return {swift::ProtocolConformanceRef(inheritedConf->getInheritedConformance())};
182+
}
183+
175184
BridgedSubstitutionMap BridgedConformance::getSpecializedSubstitutions() const {
176185
auto *specPC = swift::cast<swift::SpecializedProtocolConformance>(unbridged().getConcrete());
177186
return {specPC->getSubstitutionMap()};

lib/IRGen/GenProto.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,10 +2504,14 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol,
25042504

25052505
const ConformanceInfo *info;
25062506

2507+
auto *specConf = conformance;
2508+
if (auto *inheritedC = dyn_cast<InheritedProtocolConformance>(conformance))
2509+
specConf = inheritedC->getInheritedConformance();
2510+
25072511
// If there is a specialized SILWitnessTable for the specialized conformance,
25082512
// directly use it.
2509-
if (auto *sc = dyn_cast<SpecializedProtocolConformance>(conformance)) {
2510-
SILWitnessTable *wt = getSILModule().lookUpWitnessTable(conformance);
2513+
if (auto *sc = dyn_cast<SpecializedProtocolConformance>(specConf)) {
2514+
SILWitnessTable *wt = getSILModule().lookUpWitnessTable(specConf);
25112515
if (wt && wt->getConformance() == sc) {
25122516
info = new SpecializedConformanceInfo(sc);
25132517
Conformances.try_emplace(conformance, info);

test/embedded/existential-class-bound1.swift

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public protocol ProtoWithAssocConf: AnyObject {
5858
}
5959

6060
public class GenClass2<T>: Q {
61-
var t: T
61+
final var t: T
6262

6363
init(t : T) { self.t = t }
6464

@@ -67,13 +67,28 @@ public class GenClass2<T>: Q {
6767
}
6868
}
6969

70+
public class DerivedFromGenClass2: GenClass2<Int> {
71+
init() { super.init(t: 42) }
72+
73+
public override func bar() {
74+
print("derived-bar")
75+
}
76+
}
77+
7078
final public class GenClass3<V>: ProtoWithAssocConf {
7179
public func foo() -> GenClass2<Int> {
7280
print("foo")
7381
return GenClass2(t: 27)
7482
}
7583
}
7684

85+
final public class OtherClass: ProtoWithAssocConf {
86+
public func foo() -> GenClass2<Int> {
87+
print("other-foo")
88+
return DerivedFromGenClass2()
89+
}
90+
}
91+
7792

7893
public func createExWithAssocConf() -> any ProtoWithAssocConf {
7994
return GenClass3<Int>()
@@ -84,6 +99,21 @@ public func callExWithAssocConf(_ p: any ProtoWithAssocConf) {
8499
x.bar()
85100
}
86101

102+
public class Base<T>: ClassBound {
103+
public func foo() { print("Base.foo()") }
104+
public func bar() { print("Base.bar()") }
105+
}
106+
107+
public class Derived1: Base<Int> {
108+
public override func foo() { print("Derived1.foo()") }
109+
public override func bar() { print("Derived1.bar()") }
110+
}
111+
112+
public class Derived2<T>: Base<T> {
113+
public override func foo() { print("Derived2.foo()") }
114+
public override func bar() { print("Derived2.bar()") }
115+
}
116+
87117
@main
88118
struct Main {
89119
static func main() {
@@ -98,6 +128,15 @@ struct Main {
98128
callExWithAssocConf(createExWithAssocConf())
99129
// CHECK: foo
100130
// CHECK: bar
131+
callExWithAssocConf(OtherClass())
132+
// CHECK: other-foo
133+
// CHECK: derived-bar
134+
test(existential: Derived1())
135+
// CHECK: Derived1.foo()
136+
// CHECK: Derived1.bar()
137+
test(existential: Derived2<Bool>())
138+
// CHECK: Derived2.foo()
139+
// CHECK: Derived2.bar()
101140
}
102141
}
103142

0 commit comments

Comments
 (0)