Skip to content

Commit 4ab605e

Browse files
authored
Merge pull request swiftlang#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 *

0 commit comments

Comments
 (0)