diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index f98104dac13..3d0088c7a5d 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -1829,12 +1829,8 @@ public: void visitAssociatedTypeDecl(AssociatedTypeDecl *td) { // Find the substitution info for the witness type. - auto foundWitness = Conformance->getTypeWitnesses().find(td); - assert(foundWitness != Conformance->getTypeWitnesses().end() - && "no witness for associated type requirement"); - - Substitution witness = foundWitness->second; - + const auto &witness = Conformance->getTypeWitness(td); + // Emit the record for the type itself. Entries.push_back(SILWitnessTable::AssociatedTypeWitness{td, witness.Replacement->getCanonicalType()}); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 2ad667424ce..a036296099d 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -967,6 +967,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, // viable. if (matchWitness(TC, Proto, DC, Requirement, T, derived, TypeWitnesses).isViable()) { + Mapping[Requirement] = derived; numViable = 1; continue; } diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 99bcd94d072..82936c3a455 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -598,6 +598,42 @@ Serializer::encodeUnderlyingConformance(const ProtocolConformance *conformance, return append; } +namespace { + /// Apply the given function object to each value witness within the + /// given protocol conformance. + /// + /// The function object should accept a \c ValueDecl* for the requirement + /// followed by the \c ConcreteDeclRef for the witness. + template + void forEachValueWitness(const ProtocolConformance *conformance, F f) { + const ProtocolDecl *protocol = conformance->getProtocol(); + for (auto req : protocol->getMembers()) { + auto valueReq = dyn_cast(req); + if (!valueReq || isa(valueReq)) + continue; + + f(valueReq, conformance->getWitness(valueReq)); + } + } + + /// Apply the given function object to each type witness within the given + /// protocol conformance. + /// + /// The function object should accept an \c AssociatedTypeDecl* for the + /// requirement followed by the \c Substitution for the witness. + template + void forEachTypeWitness(const ProtocolConformance *conformance, F f) { + const ProtocolDecl *protocol = conformance->getProtocol(); + for (auto req : protocol->getMembers()) { + auto assocTypeReq = dyn_cast(req); + if (!assocTypeReq) + continue; + + f(assocTypeReq, conformance->getTypeWitness(assocTypeReq)); + } + } +} + void Serializer::writeConformance(const ProtocolDecl *protocol, const ProtocolConformance *conformance, @@ -627,18 +663,23 @@ Serializer::writeConformance(const ProtocolDecl *protocol, unsigned numValueWitnesses = 0; unsigned numTypeWitnesses = 0; unsigned numDefaultedDefinitions = 0; - for (auto valueMapping : conf->getWitnesses()) { - data.push_back(addDeclRef(valueMapping.first)); - data.push_back(addDeclRef(valueMapping.second.getDecl())); + forEachValueWitness(conformance, + [&](ValueDecl *req, ConcreteDeclRef witness) { + data.push_back(addDeclRef(req)); + data.push_back(addDeclRef(witness.getDecl())); // The substitution records are serialized later. - data.push_back(valueMapping.second.getSubstitutions().size()); + data.push_back(witness.getSubstitutions().size()); ++numValueWitnesses; - } - for (auto typeMapping : conf->getTypeWitnesses()) { - data.push_back(addDeclRef(typeMapping.first)); - // The substitution record is serialized later. - ++numTypeWitnesses; - } + }); + + forEachTypeWitness(conformance, + [&](AssociatedTypeDecl *assocType, + const Substitution &witness) { + data.push_back(addDeclRef(assocType)); + // The substitution record is serialized later. + ++numTypeWitnesses; + }); + for (auto defaulted : conf->getDefaultedDefinitions()) { data.push_back(addDeclRef(defaulted)); ++numDefaultedDefinitions; @@ -664,12 +705,15 @@ Serializer::writeConformance(const ProtocolDecl *protocol, } writeConformances(inheritedProtos, inheritedConformance, associatedDecl, abbrCodes); - for (auto valueMapping : conf->getWitnesses()) { - writeSubstitutions(valueMapping.second.getSubstitutions(), - abbrCodes); - } - for (auto typeMapping : conf->getTypeWitnesses()) - writeSubstitutions(typeMapping.second, abbrCodes); + forEachValueWitness(conformance, + [&](ValueDecl *req, ConcreteDeclRef witness) { + writeSubstitutions(witness.getSubstitutions(), abbrCodes); + }); + forEachTypeWitness(conformance, + [&](AssociatedTypeDecl *assocType, + const Substitution &witness) { + writeSubstitutions(witness, abbrCodes); + }); break; } @@ -678,11 +722,13 @@ Serializer::writeConformance(const ProtocolDecl *protocol, auto conf = cast(conformance); SmallVector data; unsigned numTypeWitnesses = 0; - for (auto typeMapping : conf->getTypeWitnesses()) { - data.push_back(addDeclRef(typeMapping.first)); - // The substitution record is serialized later. - ++numTypeWitnesses; - } + forEachTypeWitness(conf, + [&](AssociatedTypeDecl *assocType, + const Substitution &witness) { + data.push_back(addDeclRef(assocType)); + // The substitution record is serialized later. + ++numTypeWitnesses; + }); auto substitutions = conf->getGenericSubstitutions(); unsigned abbrCode = abbrCodes[SpecializedProtocolConformanceLayout::Code]; @@ -702,8 +748,12 @@ Serializer::writeConformance(const ProtocolDecl *protocol, substitutions.size(), data); writeSubstitutions(substitutions, abbrCodes); - for (auto typeMapping : conf->getTypeWitnesses()) - writeSubstitutions(typeMapping.second, abbrCodes); + + forEachTypeWitness(conformance, + [&](AssociatedTypeDecl *assocType, + const Substitution &witness) { + writeSubstitutions(witness, abbrCodes); + }); if (appendGenericConformance) { writeConformance(protocol, conf->getGenericConformance(), nullptr,