Skip to content

Commit add6f12

Browse files
authored
Merge pull request #20619 from rjmccall/self-conformance-fixes
Assorted fixes for the self-conformance infrastructure
2 parents 0d9f634 + 1065f99 commit add6f12

File tree

10 files changed

+51
-54
lines changed

10 files changed

+51
-54
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ types where the metadata itself has unknown layout.)
183183
global ::= type label-list? 'D' // type mangling for the debugger with label list for function types.
184184
global ::= type 'TC' // continuation prototype (not actually used for real symbols)
185185
global ::= protocol-conformance entity 'TW' // protocol witness thunk
186-
global ::= protocol-conformance entity 'TS' // protocol self-conformance witness thunk
186+
global ::= entity 'TS' // protocol self-conformance witness thunk
187187
global ::= context identifier identifier 'TB' // property behavior initializer thunk (not used currently)
188188
global ::= context identifier identifier 'Tb' // property behavior setter thunk (not used currently)
189189
global ::= global specialization // function specialization

include/swift/AST/ProtocolConformance.h

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,33 @@ class RootProtocolConformance : public ProtocolConformance {
364364
ConcreteDeclRef getWitnessDeclRef(ValueDecl *requirement,
365365
LazyResolver *resolver) const;
366366

367+
/// Apply the given function object to each value witness within this
368+
/// protocol conformance.
369+
///
370+
/// The function object should accept a \c ValueDecl* for the requirement
371+
/// followed by the \c Witness for the witness. Note that a generic
372+
/// witness will only be specialized if the conformance came from the current
373+
/// file.
374+
template<typename F>
375+
void forEachValueWitness(LazyResolver *resolver, F f) const {
376+
const ProtocolDecl *protocol = getProtocol();
377+
for (auto req : protocol->getMembers()) {
378+
auto valueReq = dyn_cast<ValueDecl>(req);
379+
if (!valueReq || isa<AssociatedTypeDecl>(valueReq) ||
380+
valueReq->isInvalid())
381+
continue;
382+
383+
if (!valueReq->isProtocolRequirement())
384+
continue;
385+
386+
// If we don't have and cannot resolve witnesses, skip it.
387+
if (!resolver && !hasWitness(valueReq))
388+
continue;
389+
390+
f(valueReq, getWitness(valueReq, resolver));
391+
}
392+
}
393+
367394
static bool classof(const ProtocolConformance *conformance) {
368395
return conformance->getKind() == ProtocolConformanceKind::Normal ||
369396
conformance->getKind() == ProtocolConformanceKind::Self;
@@ -639,33 +666,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
639666
/// Set the witness for the given requirement.
640667
void setWitness(ValueDecl *requirement, Witness witness) const;
641668

642-
/// Apply the given function object to each value witness within this
643-
/// protocol conformance.
644-
///
645-
/// The function object should accept a \c ValueDecl* for the requirement
646-
/// followed by the \c Witness for the witness. Note that a generic
647-
/// witness will only be specialized if the conformance came from the current
648-
/// file.
649-
template<typename F>
650-
void forEachValueWitness(LazyResolver *resolver, F f) const {
651-
const ProtocolDecl *protocol = getProtocol();
652-
for (auto req : protocol->getMembers()) {
653-
auto valueReq = dyn_cast<ValueDecl>(req);
654-
if (!valueReq || isa<AssociatedTypeDecl>(valueReq) ||
655-
valueReq->isInvalid())
656-
continue;
657-
658-
if (!valueReq->isProtocolRequirement())
659-
continue;
660-
661-
// If we don't have and cannot resolve witnesses, skip it.
662-
if (!resolver && !hasWitness(valueReq))
663-
continue;
664-
665-
f(valueReq, getWitness(valueReq, resolver));
666-
}
667-
}
668-
669669
/// Retrieve the protocol conformances that satisfy the requirements of the
670670
/// protocol, which line up with the conformance constraints in the
671671
/// protocol's requirement signature.

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,7 @@ std::string ASTMangler::mangleWitnessThunk(
201201
beginMangling();
202202
// Concrete witness thunks get a special mangling.
203203
if (Conformance) {
204-
if (auto selfConformance = dyn_cast<SelfProtocolConformance>(Conformance)) {
205-
auto protocol = cast<SelfProtocolConformance>(Conformance)->getProtocol();
206-
appendProtocolName(protocol);
207-
} else {
204+
if (!isa<SelfProtocolConformance>(Conformance)) {
208205
appendProtocolConformance(Conformance);
209206
}
210207
}

lib/Demangling/Remangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,7 @@ void Remangler::mangleProtocolRequirementsBaseDescriptor(Node *node) {
17201720
}
17211721

17221722
void Remangler::mangleProtocolSelfConformanceDescriptor(Node *node) {
1723-
mangleProtocol(node->getChild(0));
1723+
manglePureProtocol(node->getChild(0));
17241724
Buffer << "MS";
17251725
}
17261726

lib/IRGen/GenProto.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,8 +1001,15 @@ static bool hasDependentTypeWitness(const RootProtocolConformance *root) {
10011001
}
10021002

10031003
static bool isDependentConformance(
1004-
const NormalProtocolConformance *conformance,
1004+
const RootProtocolConformance *rootConformance,
10051005
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> &visited){
1006+
// Self-conformances are never dependent.
1007+
auto conformance = dyn_cast<NormalProtocolConformance>(rootConformance);
1008+
if (!conformance)
1009+
return false;
1010+
1011+
// Check whether we've visited this conformance already. If so,
1012+
// optimistically assume it's fine --- we want the maximal fixed point.
10061013
if (!visited.insert(conformance).second)
10071014
return false;
10081015

@@ -1024,7 +1031,7 @@ static bool isDependentConformance(
10241031
conformance->getAssociatedConformance(req.getFirstType(), assocProtocol);
10251032
if (assocConformance.isAbstract() ||
10261033
isDependentConformance(assocConformance.getConcrete()
1027-
->getRootNormalConformance(),
1034+
->getRootConformance(),
10281035
visited))
10291036
return true;
10301037
}
@@ -1040,18 +1047,11 @@ static bool isDependentConformance(
10401047

10411048
/// Is there anything about the given conformance that requires witness
10421049
/// tables to be dependently-generated?
1043-
static bool isDependentConformance(
1044-
const NormalProtocolConformance *conformance) {
1050+
static bool isDependentConformance(const RootProtocolConformance *conformance) {
10451051
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> visited;
10461052
return ::isDependentConformance(conformance, visited);
10471053
}
10481054

1049-
static bool isDependentConformance(const RootProtocolConformance *conformance) {
1050-
if (auto normal = dyn_cast<NormalProtocolConformance>(conformance))
1051-
return isDependentConformance(normal);
1052-
return false;
1053-
}
1054-
10551055
static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) {
10561056
if (auto normal = dyn_cast<NormalProtocolConformance>(conformance))
10571057
return normal->isSynthesizedNonUnique();

lib/IRGen/Linking.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ std::string LinkEntity::mangleAsString() const {
212212

213213
case Kind::ProtocolConformanceDescriptor:
214214
return mangler.mangleProtocolConformanceDescriptor(
215-
cast<NormalProtocolConformance>(getProtocolConformance()));
215+
getRootProtocolConformance());
216216

217217
case Kind::EnumCase:
218218
return mangler.mangleEnumCase(getDecl());
@@ -353,7 +353,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
353353
// For when `this` is a protocol conformance of some kind.
354354
auto getLinkageAsConformance = [&] {
355355
return getLinkageForProtocolConformance(
356-
getProtocolConformance()->getRootNormalConformance(), forDefinition);
356+
getProtocolConformance()->getRootConformance(), forDefinition);
357357
};
358358

359359
switch (getKind()) {

lib/IRGen/LocalTypeData.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ LocalTypeDataKind LocalTypeDataKind::getCachingKind() const {
4141

4242
// Map protocol conformances to their root normal conformance.
4343
auto conformance = getConcreteProtocolConformance();
44-
return forConcreteProtocolWitnessTable(
45-
conformance->getRootNormalConformance());
44+
return forConcreteProtocolWitnessTable(conformance->getRootConformance());
4645
}
4746

4847
LocalTypeDataCache &IRGenFunction::getOrCreateLocalTypeData() {

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4137,6 +4137,7 @@ void Serializer::writeAllDeclsAndTypes() {
41374137

41384138
registerDeclTypeAbbr<AbstractProtocolConformanceLayout>();
41394139
registerDeclTypeAbbr<NormalProtocolConformanceLayout>();
4140+
registerDeclTypeAbbr<SelfProtocolConformanceLayout>();
41404141
registerDeclTypeAbbr<SpecializedProtocolConformanceLayout>();
41414142
registerDeclTypeAbbr<InheritedProtocolConformanceLayout>();
41424143
registerDeclTypeAbbr<InvalidProtocolConformanceLayout>();

lib/Serialization/SerializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
24242424
// decl blocks and sil blocks.
24252425
registerSILAbbr<decls_block::AbstractProtocolConformanceLayout>();
24262426
registerSILAbbr<decls_block::NormalProtocolConformanceLayout>();
2427+
registerSILAbbr<decls_block::SelfProtocolConformanceLayout>();
24272428
registerSILAbbr<decls_block::SpecializedProtocolConformanceLayout>();
24282429
registerSILAbbr<decls_block::InheritedProtocolConformanceLayout>();
24292430
registerSILAbbr<decls_block::NormalProtocolConformanceIdLayout>();

lib/TBDGen/TBDGen.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,15 @@ void TBDGenVisitor::addConformances(DeclContext *DC) {
132132
ValueDecl *witnessDecl) {
133133
auto witnessLinkage = SILDeclRef(witnessDecl).getLinkage(ForDefinition);
134134
if (conformanceIsFixed &&
135-
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessLinkage)) {
135+
(isa<SelfProtocolConformance>(rootConformance) ||
136+
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessLinkage))) {
136137
Mangle::ASTMangler Mangler;
137138
addSymbol(
138139
Mangler.mangleWitnessThunk(rootConformance, requirementDecl));
139140
}
140141
};
141142

142-
// FIXME: skipping witnesses for self-conformances?
143-
auto normalConformance =
144-
dyn_cast<NormalProtocolConformance>(rootConformance);
145-
if (!normalConformance) continue;
146-
147-
normalConformance->forEachValueWitness(
143+
rootConformance->forEachValueWitness(
148144
nullptr, [&](ValueDecl *valueReq, Witness witness) {
149145
auto witnessDecl = witness.getDecl();
150146
if (isa<AbstractFunctionDecl>(valueReq)) {
@@ -464,6 +460,9 @@ void TBDGenVisitor::visitProtocolDecl(ProtocolDecl *PD) {
464460
addAssociatedTypeDescriptor(assocType);
465461
}
466462
}
463+
464+
// Include the self-conformance.
465+
addConformances(PD);
467466
}
468467

469468
#ifndef NDEBUG

0 commit comments

Comments
 (0)