Skip to content

Commit 4ab605e

Browse files
authored
Merge pull request #24083 from slavapestov/self-conformance-fix
AST: Start returning SelfProtocolConformances from ModuleDecl::lookupConformance()
2 parents cfc8409 + 5062a81 commit 4ab605e

18 files changed

+120
-133
lines changed

lib/AST/ConformanceLookupTable.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,9 +1147,9 @@ ConformanceLookupTable::getSatisfiedProtocolRequirementsForMember(
11471147
if (conf->isInvalid())
11481148
continue;
11491149

1150-
auto normal = conf->getRootNormalConformance();
1151-
normal->forEachValueWitness(nullptr,
1152-
[&](ValueDecl *req, Witness witness) {
1150+
auto root = conf->getRootConformance();
1151+
root->forEachValueWitness(nullptr,
1152+
[&](ValueDecl *req, Witness witness) {
11531153
if (witness.getDecl() == member)
11541154
reqs.push_back(req);
11551155
});

lib/AST/Module.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,8 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
586586

587587
Optional<ProtocolConformanceRef>
588588
ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
589+
ASTContext &ctx = getASTContext();
590+
589591
assert(type->isExistentialType());
590592

591593
// If the existential type cannot be represented or the protocol does not
@@ -606,7 +608,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
606608
if (protocol->requiresSelfConformanceWitnessTable() &&
607609
type->is<ProtocolType>() &&
608610
type->castTo<ProtocolType>()->getDecl() == protocol)
609-
return ProtocolConformanceRef(protocol);
611+
return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
610612

611613
return None;
612614
}
@@ -625,7 +627,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
625627
// If we found the protocol we're looking for, return an abstract
626628
// conformance to it.
627629
if (protoDecl == protocol)
628-
return ProtocolConformanceRef(protocol);
630+
return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
629631

630632
// If the protocol has a superclass constraint, we might conform
631633
// concretely.
@@ -636,7 +638,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
636638

637639
// Now check refined protocols.
638640
if (protoDecl->inheritsFrom(protocol))
639-
return ProtocolConformanceRef(protocol);
641+
return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
640642
}
641643

642644
// We didn't find our protocol in the existential's list; it doesn't
@@ -715,7 +717,7 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) {
715717
// compiler.
716718
if (auto inherited = dyn_cast<InheritedProtocolConformance>(conformance)) {
717719
// Dig out the conforming nominal type.
718-
auto rootConformance = inherited->getRootNormalConformance();
720+
auto rootConformance = inherited->getRootConformance();
719721
auto conformingClass
720722
= rootConformance->getType()->getClassOrBoundGenericClass();
721723

lib/AST/ProtocolConformance.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,12 +1055,12 @@ SpecializedProtocolConformance::getTypeWitnessAndDecl(
10551055

10561056
// Local function to determine whether we will end up referring to a
10571057
// tentative witness that may not be chosen.
1058-
auto normal = GenericConformance->getRootNormalConformance();
1058+
auto root = GenericConformance->getRootConformance();
10591059
auto isTentativeWitness = [&] {
1060-
if (normal->getState() != ProtocolConformanceState::CheckingTypeWitnesses)
1060+
if (root->getState() != ProtocolConformanceState::CheckingTypeWitnesses)
10611061
return false;
10621062

1063-
return !normal->hasTypeWitness(assocType, nullptr);
1063+
return !root->hasTypeWitness(assocType, nullptr);
10641064
};
10651065

10661066
auto genericWitnessAndDecl

lib/AST/SubstitutionMap.cpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -664,34 +664,21 @@ void SubstitutionMap::verify() const {
664664
if (conformance.isInvalid())
665665
continue;
666666

667-
// An existential type can have an abstract conformance to
668-
// AnyObject or an @objc protocol.
669-
if (conformance.isAbstract() &&
670-
substType->isExistentialType()) {
671-
auto *proto = conformance.getRequirement();
672-
if (!proto->isObjC()) {
673-
llvm::dbgs() << "Existential type conforms to something:\n";
674-
substType->dump();
675-
llvm::dbgs() << "SubstitutionMap:\n";
676-
dump(llvm::dbgs());
677-
llvm::dbgs() << "\n";
678-
}
679-
680-
assert(proto->isObjC() &&
681-
"an existential type can conform only to an "
682-
"@objc-protocol");
683-
continue;
684-
}
685667
// All of the conformances should be concrete.
686668
if (!conformance.isConcrete()) {
687-
llvm::dbgs() << "Concrete substType type:\n";
669+
llvm::dbgs() << "Concrete type cannot have abstract conformance:\n";
688670
substType->dump(llvm::dbgs());
689671
llvm::dbgs() << "SubstitutionMap:\n";
690672
dump(llvm::dbgs());
691673
llvm::dbgs() << "\n";
692674
}
693675
assert(conformance.isConcrete() && "Conformance should be concrete");
694676

677+
if (substType->isExistentialType()) {
678+
assert(isa<SelfProtocolConformance>(conformance.getConcrete()) &&
679+
"Existential type cannot have normal conformance");
680+
}
681+
695682
++conformanceIndex;
696683
}
697684
#endif

lib/AST/Type.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,8 +1612,8 @@ bool TypeBase::isBindableTo(Type b) {
16121612
if (origConf.isConcrete()) {
16131613
if (!substConf.isConcrete())
16141614
return false;
1615-
if (origConf.getConcrete()->getRootNormalConformance()
1616-
!= substConf.getConcrete()->getRootNormalConformance())
1615+
if (origConf.getConcrete()->getRootConformance()
1616+
!= substConf.getConcrete()->getRootConformance())
16171617
return false;
16181618
}
16191619
}

lib/IDE/CodeCompletion.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4252,13 +4252,12 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42524252
auto Proto = Conformance->getProtocol();
42534253
if (!Proto->isAccessibleFrom(CurrDeclContext))
42544254
continue;
4255-
auto NormalConformance = Conformance->getRootNormalConformance();
42564255
for (auto Member : Proto->getMembers()) {
42574256
auto *ATD = dyn_cast<AssociatedTypeDecl>(Member);
42584257
if (!ATD)
42594258
continue;
42604259
// FIXME: Also exclude the type alias that has already been specified.
4261-
if (!NormalConformance->hasTypeWitness(ATD) ||
4260+
if (!Conformance->hasTypeWitness(ATD) ||
42624261
!ATD->getDefaultDefinitionLoc().isNull())
42634262
continue;
42644263
addTypeAlias(ATD,

lib/IRGen/GenProto.cpp

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,16 +1509,6 @@ void WitnessTableBuilder::defineAssociatedTypeWitnessTableAccessFunction(
15091509

15101510
const ConformanceInfo *conformanceI = nullptr;
15111511

1512-
// Rewrite (abstract) self conformances to the concrete conformance.
1513-
if (associatedConformance.isAbstract() && !hasArchetype) {
1514-
// This must be a self conformance.
1515-
auto proto = associatedConformance.getRequirement();
1516-
assert(proto->requiresSelfConformanceWitnessTable());
1517-
assert(cast<ProtocolType>(associatedType)->getDecl() == proto);
1518-
auto concreteConformance = IGF.IGM.Context.getSelfConformance(proto);
1519-
associatedConformance = ProtocolConformanceRef(concreteConformance);
1520-
}
1521-
15221512
if (associatedConformance.isConcrete()) {
15231513
assert(associatedType->isEqual(associatedConformance.getConcrete()->getType()));
15241514

@@ -2750,13 +2740,8 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
27502740
// requirements of the archetype. Look at what's locally bound.
27512741
ProtocolConformance *concreteConformance;
27522742
if (conformance.isAbstract()) {
2753-
if (auto archetype = dyn_cast<ArchetypeType>(srcType))
2754-
return emitArchetypeWitnessTableRef(IGF, archetype, proto);
2755-
2756-
// Otherwise, this must be a self-conformance.
2757-
assert(proto->requiresSelfConformanceWitnessTable());
2758-
assert(cast<ProtocolType>(srcType)->getDecl() == proto);
2759-
concreteConformance = IGF.IGM.Context.getSelfConformance(proto);
2743+
auto archetype = cast<ArchetypeType>(srcType);
2744+
return emitArchetypeWitnessTableRef(IGF, archetype, proto);
27602745

27612746
// All other source types should be concrete enough that we have
27622747
// conformance info for them. However, that conformance info might be

lib/SIL/Linker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ static bool mustDeserializeProtocolConformance(SILModule &M,
192192
ProtocolConformanceRef c) {
193193
if (!c.isConcrete())
194194
return false;
195-
auto conformance = c.getConcrete()->getRootNormalConformance();
195+
auto conformance = c.getConcrete()->getRootConformance();
196196
return M.Types.protocolRequiresWitnessTable(conformance->getProtocol())
197197
&& isa<ClangModuleUnit>(conformance->getDeclContext()
198198
->getModuleScopeContext());

lib/SILGen/SILGen.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,23 +1513,26 @@ void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
15131513
return;
15141514

15151515
auto conformance = conformanceRef.getConcrete();
1516-
auto root = conformance->getRootNormalConformance();
1516+
auto normal = dyn_cast<NormalProtocolConformance>(
1517+
conformance->getRootConformance());
1518+
if (normal == nullptr)
1519+
return;
15171520

15181521
// If we already emitted this witness table, we don't need to track the fact
15191522
// we need it.
1520-
if (emittedWitnessTables.count(root))
1523+
if (emittedWitnessTables.count(normal))
15211524
return;
15221525

15231526
// If we delayed emitting this witness table, force it.
1524-
auto foundDelayed = delayedConformances.find(root);
1527+
auto foundDelayed = delayedConformances.find(normal);
15251528
if (foundDelayed != delayedConformances.end()) {
15261529
forcedConformances.push_back(*foundDelayed);
15271530
delayedConformances.erase(foundDelayed);
15281531
return;
15291532
}
15301533

15311534
// Otherwise, just remember the fact we used this conformance.
1532-
usedConformances.insert(root);
1535+
usedConformances.insert(normal);
15331536
}
15341537

15351538
void SILGenModule::useConformancesFromSubstitutions(

lib/SILGen/SILGen.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
5858
/// Mapping from SILDeclRefs to emitted SILFunctions.
5959
llvm::DenseMap<SILDeclRef, SILFunction*> emittedFunctions;
6060
/// Mapping from ProtocolConformances to emitted SILWitnessTables.
61-
llvm::DenseMap<ProtocolConformance*, SILWitnessTable*> emittedWitnessTables;
61+
llvm::DenseMap<NormalProtocolConformance*, SILWitnessTable*> emittedWitnessTables;
6262

6363
struct DelayedFunction {
6464
/// Insert the entity after the given function when it's emitted.
@@ -78,7 +78,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
7878
SILDeclRef lastEmittedFunction;
7979

8080
/// Set of used conformances for which witness tables need to be emitted.
81-
llvm::DenseSet<NormalProtocolConformance *> usedConformances;
81+
llvm::DenseSet<RootProtocolConformance *> usedConformances;
8282

8383
struct DelayedWitnessTable {
8484
NormalProtocolConformance *insertAfter;
@@ -272,7 +272,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
272272
void emitExternalDefinition(Decl *d);
273273

274274
/// Emit SIL related to a Clang-imported declaration.
275-
void emitExternalWitnessTable(ProtocolConformance *d);
275+
void emitExternalWitnessTable(NormalProtocolConformance *d);
276276

277277
/// Emit the ObjC-compatible entry point for a method.
278278
void emitObjCMethodThunk(FuncDecl *method);
@@ -287,7 +287,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
287287
void emitObjCDestructorThunk(DestructorDecl *destructor);
288288

289289
/// Get or emit the witness table for a protocol conformance.
290-
SILWitnessTable *getWitnessTable(ProtocolConformance *conformance);
290+
SILWitnessTable *getWitnessTable(NormalProtocolConformance *conformance);
291291

292292
/// Emit a protocol witness entry point.
293293
SILFunction *

lib/SILGen/SILGenDecl.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,16 +1391,15 @@ CleanupHandle SILGenFunction::enterDeinitExistentialCleanup(
13911391
return Cleanups.getTopCleanup();
13921392
}
13931393

1394-
void SILGenModule::emitExternalWitnessTable(ProtocolConformance *c) {
1395-
auto root = c->getRootNormalConformance();
1394+
void SILGenModule::emitExternalWitnessTable(NormalProtocolConformance *c) {
13961395
// Emit the witness table right now if we used it.
1397-
if (usedConformances.count(root)) {
1396+
if (usedConformances.count(c)) {
13981397
getWitnessTable(c);
13991398
return;
14001399
}
14011400
// Otherwise, remember it for later.
1402-
delayedConformances.insert({root, {lastEmittedConformance}});
1403-
lastEmittedConformance = root;
1401+
delayedConformances.insert({c, {lastEmittedConformance}});
1402+
lastEmittedConformance = c;
14041403
}
14051404

14061405
static bool isDeclaredInPrimaryFile(SILModule &M, Decl *d) {
@@ -1443,7 +1442,7 @@ void SILGenModule::emitExternalDefinition(Decl *d) {
14431442
if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto) &&
14441443
isa<NormalProtocolConformance>(c) &&
14451444
c->isComplete())
1446-
emitExternalWitnessTable(c);
1445+
emitExternalWitnessTable(cast<NormalProtocolConformance>(c));
14471446
}
14481447
break;
14491448
}

lib/SILGen/SILGenType.cpp

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,7 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
382382
IsSerialized_t Serialized;
383383

384384
SILGenConformance(SILGenModule &SGM, NormalProtocolConformance *C)
385-
// We only need to emit witness tables for base NormalProtocolConformances.
386-
: SGM(SGM), Conformance(C->getRootNormalConformance()),
385+
: SGM(SGM), Conformance(C),
387386
Linkage(getLinkageForProtocolConformance(Conformance,
388387
ForDefinition)),
389388
Serialized(isConformanceSerialized(Conformance))
@@ -454,11 +453,11 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
454453
});
455454

456455
// Emit the witness table for the base conformance if it is shared.
457-
if (getLinkageForProtocolConformance(
458-
conformance->getRootNormalConformance(),
459-
NotForDefinition)
456+
auto *normal = conformance->getRootNormalConformance();
457+
458+
if (getLinkageForProtocolConformance(normal, NotForDefinition)
460459
== SILLinkage::Shared)
461-
SGM.getWitnessTable(conformance->getRootNormalConformance());
460+
SGM.getWitnessTable(normal);
462461
}
463462

464463
Witness getWitness(ValueDecl *decl) {
@@ -571,20 +570,18 @@ getWitnessTableToInsertAfter(SILGenModule &SGM,
571570
}
572571

573572
SILWitnessTable *
574-
SILGenModule::getWitnessTable(ProtocolConformance *conformance) {
575-
auto normal = conformance->getRootNormalConformance();
576-
573+
SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
577574
// If we've already emitted this witness table, return it.
578-
auto found = emittedWitnessTables.find(normal);
575+
auto found = emittedWitnessTables.find(conformance);
579576
if (found != emittedWitnessTables.end())
580577
return found->second;
581578

582-
SILWitnessTable *table = SILGenConformance(*this, normal).emit();
583-
emittedWitnessTables.insert({normal, table});
579+
SILWitnessTable *table = SILGenConformance(*this, conformance).emit();
580+
emittedWitnessTables.insert({conformance, table});
584581

585582
// If we delayed emission of this witness table, move it to its rightful
586583
// place within the module.
587-
auto foundDelayed = delayedConformances.find(normal);
584+
auto foundDelayed = delayedConformances.find(conformance);
588585
if (foundDelayed != delayedConformances.end()) {
589586
M.witnessTables.remove(table);
590587
auto insertAfter = getWitnessTableToInsertAfter(*this,
@@ -597,7 +594,7 @@ SILGenModule::getWitnessTable(ProtocolConformance *conformance) {
597594
} else {
598595
// We would have marked a delayed conformance as "last emitted" when it
599596
// was delayed.
600-
lastEmittedConformance = normal;
597+
lastEmittedConformance = conformance;
601598
}
602599
return table;
603600
}
@@ -978,9 +975,10 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
978975
// are existential and do not have witness tables.
979976
for (auto *conformance : theType->getLocalConformances(
980977
ConformanceLookupKind::All, nullptr)) {
981-
if (conformance->isComplete() &&
982-
isa<NormalProtocolConformance>(conformance))
983-
SGM.getWitnessTable(conformance);
978+
if (conformance->isComplete()) {
979+
if (auto *normal = dyn_cast<NormalProtocolConformance>(conformance))
980+
SGM.getWitnessTable(normal);
981+
}
984982
}
985983
}
986984

@@ -1085,9 +1083,10 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
10851083
for (auto *conformance : e->getLocalConformances(
10861084
ConformanceLookupKind::All,
10871085
nullptr)) {
1088-
if (conformance->isComplete() &&
1089-
isa<NormalProtocolConformance>(conformance))
1090-
SGM.getWitnessTable(conformance);
1086+
if (conformance->isComplete()) {
1087+
if (auto *normal =dyn_cast<NormalProtocolConformance>(conformance))
1088+
SGM.getWitnessTable(normal);
1089+
}
10911090
}
10921091
}
10931092
}

lib/SILOptimizer/Utils/Devirtualize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,7 @@ getWitnessMethodSubstitutions(
905905
auto baseSubMap = conformance->getSubstitutions(mod);
906906

907907
unsigned baseDepth = 0;
908-
auto *rootConformance = conformance->getRootNormalConformance();
908+
auto *rootConformance = conformance->getRootConformance();
909909
if (auto *witnessSig = rootConformance->getGenericSignature())
910910
baseDepth = witnessSig->getGenericParams().back()->getDepth() + 1;
911911

0 commit comments

Comments
 (0)