Skip to content

Commit a67d9c5

Browse files
committed
embedded: Support class existentials with inherited protocols
For example: ``` protocol Base: AnyObject {} protocol Derived: Base {} class C: Derived {} let e: Derived = C() ```
1 parent db4c28a commit a67d9c5

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,16 @@ func specializeWitnessTable(forConformance conformance: Conformance,
102102
return origEntry
103103
}
104104
return .method(requirement: requirement, witness: specializedMethod)
105+
case .baseProtocol(let requirement, let witness):
106+
let baseConf = context.getSpecializedConformance(of: witness,
107+
for: conformance.type,
108+
substitutions: conformance.specializedSubstitutions)
109+
specializeWitnessTable(forConformance: baseConf, errorLocation: errorLocation, context, notifyNewWitnessTable)
110+
return .baseProtocol(requirement: requirement, witness: baseConf)
105111
default:
106112
// TODO: handle other witness table entry kinds
107113
fatalError("unsupported witness table etnry")
108114
}
109-
return origEntry
110115
}
111116
let newWT = context.createWitnessTable(entries: newEntries,conformance: conformance,
112117
linkage: .shared, serialized: false)

lib/IRGen/GenProto.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,12 +1563,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
15631563
/// A base protocol is witnessed by a pointer to the conformance
15641564
/// of this type to that protocol.
15651565
void addOutOfLineBaseProtocol(ProtocolDecl *baseProto) {
1566-
#ifndef NDEBUG
15671566
auto &entry = SILEntries.front();
1568-
#endif
15691567
SILEntries = SILEntries.slice(1);
15701568

1571-
#ifndef NDEBUG
15721569
assert(entry.getKind() == SILWitnessTable::BaseProtocol
15731570
&& "sil witness table does not match protocol");
15741571
assert(entry.getBaseProtocolWitness().Requirement == baseProto
@@ -1577,13 +1574,18 @@ class AccessorConformanceInfo : public ConformanceInfo {
15771574
assert((size_t)piIndex.getValue() ==
15781575
Table.size() - WitnessTableFirstRequirementOffset &&
15791576
"offset doesn't match ProtocolInfo layout");
1580-
#endif
15811577

15821578
// TODO: Use the witness entry instead of falling through here.
15831579

15841580
// Look for conformance info.
1585-
auto *astConf = ConformanceInContext.getInheritedConformance(baseProto);
1586-
assert(astConf->getType()->isEqual(ConcreteType));
1581+
ProtocolConformance *astConf = nullptr;
1582+
if (isa<SpecializedProtocolConformance>(SILWT->getConformance())) {
1583+
astConf = entry.getBaseProtocolWitness().Witness;
1584+
ASSERT(isa<SpecializedProtocolConformance>(astConf));
1585+
} else {
1586+
astConf = ConformanceInContext.getInheritedConformance(baseProto);
1587+
assert(astConf->getType()->isEqual(ConcreteType));
1588+
}
15871589
const ConformanceInfo &conf = IGM.getConformanceInfo(baseProto, astConf);
15881590

15891591
// If we can emit the base witness table as a constant, do so.

test/embedded/existential-class-bound4.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
// REQUIRES: optimized_stdlib
66
// REQUIRES: OS=macosx || OS=linux-gnu
77

8-
protocol ClassBound: AnyObject {
8+
public protocol Base: AnyObject {
99
func foo()
10+
}
11+
12+
protocol ClassBound: Base {
1013
func bar()
1114
}
1215

0 commit comments

Comments
 (0)