Skip to content

AST: Start returning SelfProtocolConformances from ModuleDecl::lookupConformance() #24083

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/AST/ConformanceLookupTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,9 +1147,9 @@ ConformanceLookupTable::getSatisfiedProtocolRequirementsForMember(
if (conf->isInvalid())
continue;

auto normal = conf->getRootNormalConformance();
normal->forEachValueWitness(nullptr,
[&](ValueDecl *req, Witness witness) {
auto root = conf->getRootConformance();
root->forEachValueWitness(nullptr,
[&](ValueDecl *req, Witness witness) {
if (witness.getDecl() == member)
reqs.push_back(req);
});
Expand Down
10 changes: 6 additions & 4 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,8 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {

Optional<ProtocolConformanceRef>
ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
ASTContext &ctx = getASTContext();

assert(type->isExistentialType());

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

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

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

// Now check refined protocols.
if (protoDecl->inheritsFrom(protocol))
return ProtocolConformanceRef(protocol);
return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
}

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

Expand Down
6 changes: 3 additions & 3 deletions lib/AST/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1055,12 +1055,12 @@ SpecializedProtocolConformance::getTypeWitnessAndDecl(

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

return !normal->hasTypeWitness(assocType, nullptr);
return !root->hasTypeWitness(assocType, nullptr);
};

auto genericWitnessAndDecl
Expand Down
25 changes: 6 additions & 19 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,34 +664,21 @@ void SubstitutionMap::verify() const {
if (conformance.isInvalid())
continue;

// An existential type can have an abstract conformance to
// AnyObject or an @objc protocol.
if (conformance.isAbstract() &&
substType->isExistentialType()) {
auto *proto = conformance.getRequirement();
if (!proto->isObjC()) {
llvm::dbgs() << "Existential type conforms to something:\n";
substType->dump();
llvm::dbgs() << "SubstitutionMap:\n";
dump(llvm::dbgs());
llvm::dbgs() << "\n";
}

assert(proto->isObjC() &&
"an existential type can conform only to an "
"@objc-protocol");
continue;
}
// All of the conformances should be concrete.
if (!conformance.isConcrete()) {
llvm::dbgs() << "Concrete substType type:\n";
llvm::dbgs() << "Concrete type cannot have abstract conformance:\n";
substType->dump(llvm::dbgs());
llvm::dbgs() << "SubstitutionMap:\n";
dump(llvm::dbgs());
llvm::dbgs() << "\n";
}
assert(conformance.isConcrete() && "Conformance should be concrete");

if (substType->isExistentialType()) {
assert(isa<SelfProtocolConformance>(conformance.getConcrete()) &&
"Existential type cannot have normal conformance");
}

++conformanceIndex;
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1612,8 +1612,8 @@ bool TypeBase::isBindableTo(Type b) {
if (origConf.isConcrete()) {
if (!substConf.isConcrete())
return false;
if (origConf.getConcrete()->getRootNormalConformance()
!= substConf.getConcrete()->getRootNormalConformance())
if (origConf.getConcrete()->getRootConformance()
!= substConf.getConcrete()->getRootConformance())
return false;
}
}
Expand Down
3 changes: 1 addition & 2 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4252,13 +4252,12 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
auto Proto = Conformance->getProtocol();
if (!Proto->isAccessibleFrom(CurrDeclContext))
continue;
auto NormalConformance = Conformance->getRootNormalConformance();
for (auto Member : Proto->getMembers()) {
auto *ATD = dyn_cast<AssociatedTypeDecl>(Member);
if (!ATD)
continue;
// FIXME: Also exclude the type alias that has already been specified.
if (!NormalConformance->hasTypeWitness(ATD) ||
if (!Conformance->hasTypeWitness(ATD) ||
!ATD->getDefaultDefinitionLoc().isNull())
continue;
addTypeAlias(ATD,
Expand Down
19 changes: 2 additions & 17 deletions lib/IRGen/GenProto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1509,16 +1509,6 @@ void WitnessTableBuilder::defineAssociatedTypeWitnessTableAccessFunction(

const ConformanceInfo *conformanceI = nullptr;

// Rewrite (abstract) self conformances to the concrete conformance.
if (associatedConformance.isAbstract() && !hasArchetype) {
// This must be a self conformance.
auto proto = associatedConformance.getRequirement();
assert(proto->requiresSelfConformanceWitnessTable());
assert(cast<ProtocolType>(associatedType)->getDecl() == proto);
auto concreteConformance = IGF.IGM.Context.getSelfConformance(proto);
associatedConformance = ProtocolConformanceRef(concreteConformance);
}

if (associatedConformance.isConcrete()) {
assert(associatedType->isEqual(associatedConformance.getConcrete()->getType()));

Expand Down Expand Up @@ -2750,13 +2740,8 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
// requirements of the archetype. Look at what's locally bound.
ProtocolConformance *concreteConformance;
if (conformance.isAbstract()) {
if (auto archetype = dyn_cast<ArchetypeType>(srcType))
return emitArchetypeWitnessTableRef(IGF, archetype, proto);

// Otherwise, this must be a self-conformance.
assert(proto->requiresSelfConformanceWitnessTable());
assert(cast<ProtocolType>(srcType)->getDecl() == proto);
concreteConformance = IGF.IGM.Context.getSelfConformance(proto);
auto archetype = cast<ArchetypeType>(srcType);
return emitArchetypeWitnessTableRef(IGF, archetype, proto);

// All other source types should be concrete enough that we have
// conformance info for them. However, that conformance info might be
Expand Down
2 changes: 1 addition & 1 deletion lib/SIL/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ static bool mustDeserializeProtocolConformance(SILModule &M,
ProtocolConformanceRef c) {
if (!c.isConcrete())
return false;
auto conformance = c.getConcrete()->getRootNormalConformance();
auto conformance = c.getConcrete()->getRootConformance();
return M.Types.protocolRequiresWitnessTable(conformance->getProtocol())
&& isa<ClangModuleUnit>(conformance->getDeclContext()
->getModuleScopeContext());
Expand Down
11 changes: 7 additions & 4 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1513,23 +1513,26 @@ void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
return;

auto conformance = conformanceRef.getConcrete();
auto root = conformance->getRootNormalConformance();
auto normal = dyn_cast<NormalProtocolConformance>(
conformance->getRootConformance());
if (normal == nullptr)
return;

// If we already emitted this witness table, we don't need to track the fact
// we need it.
if (emittedWitnessTables.count(root))
if (emittedWitnessTables.count(normal))
return;

// If we delayed emitting this witness table, force it.
auto foundDelayed = delayedConformances.find(root);
auto foundDelayed = delayedConformances.find(normal);
if (foundDelayed != delayedConformances.end()) {
forcedConformances.push_back(*foundDelayed);
delayedConformances.erase(foundDelayed);
return;
}

// Otherwise, just remember the fact we used this conformance.
usedConformances.insert(root);
usedConformances.insert(normal);
}

void SILGenModule::useConformancesFromSubstitutions(
Expand Down
8 changes: 4 additions & 4 deletions lib/SILGen/SILGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
/// Mapping from SILDeclRefs to emitted SILFunctions.
llvm::DenseMap<SILDeclRef, SILFunction*> emittedFunctions;
/// Mapping from ProtocolConformances to emitted SILWitnessTables.
llvm::DenseMap<ProtocolConformance*, SILWitnessTable*> emittedWitnessTables;
llvm::DenseMap<NormalProtocolConformance*, SILWitnessTable*> emittedWitnessTables;

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

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

struct DelayedWitnessTable {
NormalProtocolConformance *insertAfter;
Expand Down Expand Up @@ -272,7 +272,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
void emitExternalDefinition(Decl *d);

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

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

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

/// Emit a protocol witness entry point.
SILFunction *
Expand Down
11 changes: 5 additions & 6 deletions lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1391,16 +1391,15 @@ CleanupHandle SILGenFunction::enterDeinitExistentialCleanup(
return Cleanups.getTopCleanup();
}

void SILGenModule::emitExternalWitnessTable(ProtocolConformance *c) {
auto root = c->getRootNormalConformance();
void SILGenModule::emitExternalWitnessTable(NormalProtocolConformance *c) {
// Emit the witness table right now if we used it.
if (usedConformances.count(root)) {
if (usedConformances.count(c)) {
getWitnessTable(c);
return;
}
// Otherwise, remember it for later.
delayedConformances.insert({root, {lastEmittedConformance}});
lastEmittedConformance = root;
delayedConformances.insert({c, {lastEmittedConformance}});
lastEmittedConformance = c;
}

static bool isDeclaredInPrimaryFile(SILModule &M, Decl *d) {
Expand Down Expand Up @@ -1443,7 +1442,7 @@ void SILGenModule::emitExternalDefinition(Decl *d) {
if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto) &&
isa<NormalProtocolConformance>(c) &&
c->isComplete())
emitExternalWitnessTable(c);
emitExternalWitnessTable(cast<NormalProtocolConformance>(c));
}
break;
}
Expand Down
39 changes: 19 additions & 20 deletions lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,7 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
IsSerialized_t Serialized;

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

// Emit the witness table for the base conformance if it is shared.
if (getLinkageForProtocolConformance(
conformance->getRootNormalConformance(),
NotForDefinition)
auto *normal = conformance->getRootNormalConformance();

if (getLinkageForProtocolConformance(normal, NotForDefinition)
== SILLinkage::Shared)
SGM.getWitnessTable(conformance->getRootNormalConformance());
SGM.getWitnessTable(normal);
}

Witness getWitness(ValueDecl *decl) {
Expand Down Expand Up @@ -571,20 +570,18 @@ getWitnessTableToInsertAfter(SILGenModule &SGM,
}

SILWitnessTable *
SILGenModule::getWitnessTable(ProtocolConformance *conformance) {
auto normal = conformance->getRootNormalConformance();

SILGenModule::getWitnessTable(NormalProtocolConformance *conformance) {
// If we've already emitted this witness table, return it.
auto found = emittedWitnessTables.find(normal);
auto found = emittedWitnessTables.find(conformance);
if (found != emittedWitnessTables.end())
return found->second;

SILWitnessTable *table = SILGenConformance(*this, normal).emit();
emittedWitnessTables.insert({normal, table});
SILWitnessTable *table = SILGenConformance(*this, conformance).emit();
emittedWitnessTables.insert({conformance, table});

// If we delayed emission of this witness table, move it to its rightful
// place within the module.
auto foundDelayed = delayedConformances.find(normal);
auto foundDelayed = delayedConformances.find(conformance);
if (foundDelayed != delayedConformances.end()) {
M.witnessTables.remove(table);
auto insertAfter = getWitnessTableToInsertAfter(*this,
Expand All @@ -597,7 +594,7 @@ SILGenModule::getWitnessTable(ProtocolConformance *conformance) {
} else {
// We would have marked a delayed conformance as "last emitted" when it
// was delayed.
lastEmittedConformance = normal;
lastEmittedConformance = conformance;
}
return table;
}
Expand Down Expand Up @@ -978,9 +975,10 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
// are existential and do not have witness tables.
for (auto *conformance : theType->getLocalConformances(
ConformanceLookupKind::All, nullptr)) {
if (conformance->isComplete() &&
isa<NormalProtocolConformance>(conformance))
SGM.getWitnessTable(conformance);
if (conformance->isComplete()) {
if (auto *normal = dyn_cast<NormalProtocolConformance>(conformance))
SGM.getWitnessTable(normal);
}
}
}

Expand Down Expand Up @@ -1085,9 +1083,10 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
for (auto *conformance : e->getLocalConformances(
ConformanceLookupKind::All,
nullptr)) {
if (conformance->isComplete() &&
isa<NormalProtocolConformance>(conformance))
SGM.getWitnessTable(conformance);
if (conformance->isComplete()) {
if (auto *normal =dyn_cast<NormalProtocolConformance>(conformance))
SGM.getWitnessTable(normal);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Utils/Devirtualize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ getWitnessMethodSubstitutions(
auto baseSubMap = conformance->getSubstitutions(mod);

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

Expand Down
Loading