Introduce ProtocolConformanceRef. NFC.

The main idea here is that we really, really want to be
able to recover the protocol requirement of a conformance
reference even if it's abstract due to the conforming type
being abstract (e.g. an archetype).  I've made the conversion
from ProtocolConformance* explicit to discourage casual
contamination of the Ref with a null value.

As part of this change, always make conformance arrays in
Substitutions fully parallel to the requirements, as opposed
to occasionally being empty when the conformances are abstract.

As another part of this, I've tried to proactively fix
prospective bugs with partially-concrete conformances, which I
believe can happen with concretely-bound archetypes.

In addition to just giving us stronger invariants, this is
progress towards the removal of the archetype from Substitution.
This commit is contained in:
John McCall
2016-01-08 00:08:34 -08:00
parent 3771e9d9ee
commit 2df6880617
54 changed files with 644 additions and 455 deletions

View File

@@ -154,14 +154,22 @@ SILModule::createWitnessTableDeclaration(ProtocolConformance *C,
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
SILModule::
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily) {
// If we have a null conformance passed in (a legal value), just return
lookUpWitnessTable(ProtocolConformanceRef C, bool deserializeLazily) {
// If we have an abstract conformance passed in (a legal value), just return
// nullptr.
ArrayRef<Substitution> Subs;
if (!C)
return {nullptr, Subs};
if (!C.isConcrete())
return {nullptr, {}};
return lookUpWitnessTable(C.getConcrete());
}
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
SILModule::
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily) {
assert(C && "null conformance passed to lookUpWitnessTable");
// Walk down to the base NormalProtocolConformance.
ArrayRef<Substitution> Subs;
const ProtocolConformance *ParentC = C;
while (!isa<NormalProtocolConformance>(ParentC)) {
switch (ParentC->getKind()) {
@@ -615,7 +623,7 @@ SerializedSILLoader *SILModule::getSILLoader() {
/// required. Notice that we do not scan the class hierarchy, just the concrete
/// class type.
std::tuple<SILFunction *, SILWitnessTable *, ArrayRef<Substitution>>
SILModule::lookUpFunctionInWitnessTable(const ProtocolConformance *C,
SILModule::lookUpFunctionInWitnessTable(ProtocolConformanceRef C,
SILDeclRef Member) {
// Look up the witness table associated with our protocol conformance from the
// SILModule.
@@ -624,7 +632,7 @@ SILModule::lookUpFunctionInWitnessTable(const ProtocolConformance *C,
// If no witness table was found, bail.
if (!Ret.first) {
DEBUG(llvm::dbgs() << " Failed speculative lookup of witness for: ";
if (C) C->dump(); else Member.dump());
C.dump(); Member.dump());
return std::make_tuple(nullptr, nullptr, ArrayRef<Substitution>());
}