mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Module file] (De-)serialize inherited protocol conformances.
Swift SVN r6886
This commit is contained in:
@@ -198,6 +198,47 @@ Pattern *ModuleFile::maybeReadPattern() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProtocolConformance *
|
||||||
|
ModuleFile::readUnderlyingConformance(ProtocolDecl *proto,
|
||||||
|
DeclID nominalID,
|
||||||
|
IdentifierID moduleOrTypeID) {
|
||||||
|
if (!nominalID) {
|
||||||
|
// The underlying conformance is in the following record.
|
||||||
|
return maybeReadConformance(getType(moduleOrTypeID))->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dig out the protocol conformance within the nominal declaration.
|
||||||
|
auto nominal = cast<NominalTypeDecl>(getDecl(nominalID));
|
||||||
|
Module *owningModule;
|
||||||
|
if (moduleOrTypeID == 0)
|
||||||
|
owningModule = ModuleContext;
|
||||||
|
else
|
||||||
|
owningModule = getModule(getIdentifier(moduleOrTypeID-1));
|
||||||
|
(void)owningModule; // FIXME: Currently only used for checking.
|
||||||
|
|
||||||
|
// Search protocols
|
||||||
|
for (unsigned i = 0, n = nominal->getProtocols().size(); i != n; ++i) {
|
||||||
|
if (nominal->getProtocols()[i] == proto) {
|
||||||
|
// FIXME: Eventually, filter by owning module.
|
||||||
|
assert(nominal->getModuleContext() == owningModule);
|
||||||
|
return nominal->getConformances()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search extensions.
|
||||||
|
for (auto ext : nominal->getExtensions()) {
|
||||||
|
for (unsigned i = 0, n = ext->getProtocols().size(); i != n; ++i) {
|
||||||
|
if (ext->getProtocols()[i] == proto) {
|
||||||
|
// FIXME: Eventually, filter by owning module.
|
||||||
|
assert(ext->getModuleContext() == owningModule);
|
||||||
|
return ext->getConformances()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_unreachable("Unable to find underlying conformance");
|
||||||
|
}
|
||||||
|
|
||||||
Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
||||||
using namespace decls_block;
|
using namespace decls_block;
|
||||||
|
|
||||||
@@ -222,8 +263,6 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SPECIALIZED_PROTOCOL_CONFORMANCE: {
|
case SPECIALIZED_PROTOCOL_CONFORMANCE: {
|
||||||
lastRecordOffset.reset();
|
|
||||||
|
|
||||||
DeclID protoID;
|
DeclID protoID;
|
||||||
DeclID nominalID;
|
DeclID nominalID;
|
||||||
IdentifierID moduleOrTypeID;
|
IdentifierID moduleOrTypeID;
|
||||||
@@ -262,51 +301,12 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
|||||||
}
|
}
|
||||||
assert(rawIDIter <= rawIDs.end() && "read too much");
|
assert(rawIDIter <= rawIDs.end() && "read too much");
|
||||||
|
|
||||||
|
ProtocolConformance *genericConformance
|
||||||
|
= readUnderlyingConformance(proto, nominalID, moduleOrTypeID);
|
||||||
|
|
||||||
// Reset the offset RAII to the end of the trailing records.
|
// Reset the offset RAII to the end of the trailing records.
|
||||||
lastRecordOffset.reset();
|
lastRecordOffset.reset();
|
||||||
|
|
||||||
ProtocolConformance *genericConformance = nullptr;
|
|
||||||
|
|
||||||
if (nominalID) {
|
|
||||||
// Dig out the protocol conformance within the nominal declaration.
|
|
||||||
auto nominal = cast<NominalTypeDecl>(getDecl(nominalID));
|
|
||||||
Module *owningModule;
|
|
||||||
if (moduleOrTypeID == 0)
|
|
||||||
owningModule = ModuleContext;
|
|
||||||
else
|
|
||||||
owningModule = getModule(getIdentifier(moduleOrTypeID-1));
|
|
||||||
(void)owningModule; // FIXME: Currently only used for checking.
|
|
||||||
|
|
||||||
for (unsigned i = 0, n = nominal->getProtocols().size(); i != n; ++i) {
|
|
||||||
if (nominal->getProtocols()[i] == proto) {
|
|
||||||
genericConformance = nominal->getConformances()[i];
|
|
||||||
// FIXME: Eventually, filter by owning module.
|
|
||||||
assert(nominal->getModuleContext() == owningModule);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!genericConformance) {
|
|
||||||
for (auto ext : nominal->getExtensions()) {
|
|
||||||
for (unsigned i = 0, n = ext->getProtocols().size(); i != n; ++i) {
|
|
||||||
if (ext->getProtocols()[i] == proto) {
|
|
||||||
genericConformance = ext->getConformances()[i];
|
|
||||||
// FIXME: Eventually, filter by owning module.
|
|
||||||
assert(ext->getModuleContext() == owningModule);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (genericConformance)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The generic conformance is in the following record.
|
|
||||||
genericConformance
|
|
||||||
= maybeReadConformance(getType(moduleOrTypeID))->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(genericConformance && "Missing generic conformance?");
|
assert(genericConformance && "Missing generic conformance?");
|
||||||
return { proto,
|
return { proto,
|
||||||
ctx.getSpecializedConformance(conformingType,
|
ctx.getSpecializedConformance(conformingType,
|
||||||
@@ -316,8 +316,26 @@ Optional<ConformancePair> ModuleFile::maybeReadConformance(Type conformingType){
|
|||||||
}
|
}
|
||||||
|
|
||||||
case INHERITED_PROTOCOL_CONFORMANCE: {
|
case INHERITED_PROTOCOL_CONFORMANCE: {
|
||||||
// FIXME: Does this even make sense?
|
DeclID protoID;
|
||||||
llvm_unreachable("Not implemented");
|
DeclID nominalID;
|
||||||
|
IdentifierID moduleOrTypeID;
|
||||||
|
InheritedProtocolConformanceLayout::readRecord(scratch, protoID,
|
||||||
|
nominalID,
|
||||||
|
moduleOrTypeID);
|
||||||
|
|
||||||
|
ASTContext &ctx = ModuleContext->Ctx;
|
||||||
|
|
||||||
|
auto proto = cast<ProtocolDecl>(getDecl(protoID));
|
||||||
|
|
||||||
|
ProtocolConformance *inheritedConformance
|
||||||
|
= readUnderlyingConformance(proto, nominalID, moduleOrTypeID);
|
||||||
|
|
||||||
|
// Reset the offset RAII to the end of the trailing records.
|
||||||
|
lastRecordOffset.reset();
|
||||||
|
assert(inheritedConformance && "Missing generic conformance?");
|
||||||
|
return { proto,
|
||||||
|
ctx.getInheritedConformance(conformingType,
|
||||||
|
inheritedConformance) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a protocol conformance.
|
// Not a protocol conformance.
|
||||||
|
|||||||
@@ -194,6 +194,13 @@ private:
|
|||||||
/// If the record at the cursor is not a pattern, returns null.
|
/// If the record at the cursor is not a pattern, returns null.
|
||||||
Pattern *maybeReadPattern();
|
Pattern *maybeReadPattern();
|
||||||
|
|
||||||
|
/// Read the underlying conformance for a specialized or inherited
|
||||||
|
/// protocol conformance.
|
||||||
|
ProtocolConformance *
|
||||||
|
readUnderlyingConformance(ProtocolDecl *proto,
|
||||||
|
serialization::DeclID nominalID,
|
||||||
|
serialization::IdentifierID moduleOrTypeID);
|
||||||
|
|
||||||
/// Recursively reads a protocol conformance from \c DeclTypeCursor.
|
/// Recursively reads a protocol conformance from \c DeclTypeCursor.
|
||||||
///
|
///
|
||||||
/// The conformance will be newly-created; it's likely that it already exists
|
/// The conformance will be newly-created; it's likely that it already exists
|
||||||
|
|||||||
@@ -666,10 +666,10 @@ namespace decls_block {
|
|||||||
using SpecializedProtocolConformanceLayout = BCRecordLayout<
|
using SpecializedProtocolConformanceLayout = BCRecordLayout<
|
||||||
SPECIALIZED_PROTOCOL_CONFORMANCE,
|
SPECIALIZED_PROTOCOL_CONFORMANCE,
|
||||||
DeclIDField, // the protocol
|
DeclIDField, // the protocol
|
||||||
DeclIDField, // the nominal type decl for the normal conformance,
|
DeclIDField, // the nominal type decl for the generic conformance,
|
||||||
// or zero to indicate that the generic conformance
|
// or zero to indicate that the generic conformance
|
||||||
// is in the following record
|
// is in the following record
|
||||||
IdentifierIDField, // the module in which the normal conformance occurs,
|
IdentifierIDField, // the module in which the generic conformance occurs,
|
||||||
// or the conforming type for the generic conformance
|
// or the conforming type for the generic conformance
|
||||||
// record that follows
|
// record that follows
|
||||||
BCVBR<5>, // type mapping count
|
BCVBR<5>, // type mapping count
|
||||||
@@ -681,7 +681,13 @@ namespace decls_block {
|
|||||||
|
|
||||||
using InheritedProtocolConformanceLayout = BCRecordLayout<
|
using InheritedProtocolConformanceLayout = BCRecordLayout<
|
||||||
INHERITED_PROTOCOL_CONFORMANCE,
|
INHERITED_PROTOCOL_CONFORMANCE,
|
||||||
DeclIDField // the protocol
|
DeclIDField, // the protocol
|
||||||
|
DeclIDField, // the nominal type decl for the inherited conformance,
|
||||||
|
// or zero to indicate that the inherited conformance
|
||||||
|
// is in the following record
|
||||||
|
IdentifierIDField // the module in which the inherited conformance occurs,
|
||||||
|
// or the conforming type for the inherited conformance
|
||||||
|
// record that follows
|
||||||
>;
|
>;
|
||||||
|
|
||||||
using DeclContextLayout = BCRecordLayout<
|
using DeclContextLayout = BCRecordLayout<
|
||||||
|
|||||||
@@ -190,6 +190,23 @@ namespace {
|
|||||||
/// Writes a list of generic substitutions.
|
/// Writes a list of generic substitutions.
|
||||||
void writeSubstitutions(ArrayRef<Substitution> substitutions);
|
void writeSubstitutions(ArrayRef<Substitution> substitutions);
|
||||||
|
|
||||||
|
/// Encode the underlying conformance of a generic or specialized
|
||||||
|
/// conformance.
|
||||||
|
///
|
||||||
|
/// \param conformance The conformance we're encoding.
|
||||||
|
///
|
||||||
|
/// \param nominalID Will be set to the "nominal ID" value to be stored
|
||||||
|
/// in the parent record.
|
||||||
|
///
|
||||||
|
/// \param moduleOrTypeID Will be set to the "module or type ID" value to
|
||||||
|
/// be stored in the parent record.
|
||||||
|
///
|
||||||
|
/// \returns true if the underlying conformance will need to be written
|
||||||
|
/// out as its own record following the parent record.
|
||||||
|
bool encodeUnderlyingConformance(const ProtocolConformance *conformance,
|
||||||
|
DeclID &nominalID,
|
||||||
|
IdentifierID &moduleOrTypeID);
|
||||||
|
|
||||||
/// Writes a protocol conformance.
|
/// Writes a protocol conformance.
|
||||||
void writeConformance(const ProtocolDecl *protocol,
|
void writeConformance(const ProtocolDecl *protocol,
|
||||||
const ProtocolConformance *conformance);
|
const ProtocolConformance *conformance);
|
||||||
@@ -707,6 +724,30 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Serializer::encodeUnderlyingConformance(const ProtocolConformance *conformance,
|
||||||
|
DeclID &nominalID,
|
||||||
|
IdentifierID &moduleOrTypeID) {
|
||||||
|
bool append = !isa<NormalProtocolConformance>(conformance);
|
||||||
|
if (append) {
|
||||||
|
// Set nominalID to 0 to indicate that the generic conformance will
|
||||||
|
// follow. Encode the type in moduleOrTypeID.
|
||||||
|
nominalID = 0;
|
||||||
|
moduleOrTypeID = addTypeRef(conformance->getType());
|
||||||
|
} else {
|
||||||
|
nominalID = addDeclRef(conformance->getType()->getAnyNominal());
|
||||||
|
assert(nominalID && "Missing nominal type for specialized conformance");
|
||||||
|
|
||||||
|
// Use '0' to mean 'this module', and add 1 to any other module reference.
|
||||||
|
if (conformance->getContainingModule() == TU)
|
||||||
|
moduleOrTypeID = 0;
|
||||||
|
else
|
||||||
|
moduleOrTypeID = addModuleRef(conformance->getContainingModule()) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return append;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Serializer::writeConformance(const ProtocolDecl *protocol,
|
Serializer::writeConformance(const ProtocolDecl *protocol,
|
||||||
const ProtocolConformance *conformance) {
|
const ProtocolConformance *conformance) {
|
||||||
@@ -786,23 +827,8 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
|||||||
IdentifierID moduleOrTypeID;
|
IdentifierID moduleOrTypeID;
|
||||||
|
|
||||||
bool appendGenericConformance
|
bool appendGenericConformance
|
||||||
= !isa<NormalProtocolConformance>(conf->getGenericConformance());
|
= encodeUnderlyingConformance(conf->getGenericConformance(),
|
||||||
if (appendGenericConformance) {
|
nominalID, moduleOrTypeID);
|
||||||
// Set nominalID to 0 to indicate that the generic conformance will
|
|
||||||
// follow. Encode the type in moduleOrTypeID.
|
|
||||||
nominalID = 0;
|
|
||||||
moduleOrTypeID = addTypeRef(conf->getGenericConformance()->getType());
|
|
||||||
} else {
|
|
||||||
nominalID
|
|
||||||
= addDeclRef(conf->getGenericConformance()->getType()->getAnyNominal());
|
|
||||||
assert(nominalID && "Missing nominal type for specialized conformance");
|
|
||||||
|
|
||||||
// Use '0' to mean 'this module', and add 1 to any other module reference.
|
|
||||||
if (conf->getContainingModule() == TU)
|
|
||||||
moduleOrTypeID = 0;
|
|
||||||
else
|
|
||||||
moduleOrTypeID = addModuleRef(conf->getContainingModule()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecializedProtocolConformanceLayout::emitRecord(Out, ScratchRecord,
|
SpecializedProtocolConformanceLayout::emitRecord(Out, ScratchRecord,
|
||||||
abbrCode,
|
abbrCode,
|
||||||
@@ -823,8 +849,25 @@ Serializer::writeConformance(const ProtocolDecl *protocol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ProtocolConformanceKind::Inherited: {
|
case ProtocolConformanceKind::Inherited: {
|
||||||
// FIXME: inherited conformance might not make sense?
|
auto conf = cast<InheritedProtocolConformance>(conformance);
|
||||||
llvm_unreachable("Not implemented");
|
unsigned abbrCode
|
||||||
|
= DeclTypeAbbrCodes[InheritedProtocolConformanceLayout::Code];
|
||||||
|
DeclID nominalID;
|
||||||
|
IdentifierID moduleOrTypeID;
|
||||||
|
|
||||||
|
bool appendInheritedConformance
|
||||||
|
= encodeUnderlyingConformance(conf->getInheritedConformance(),
|
||||||
|
nominalID, moduleOrTypeID);
|
||||||
|
|
||||||
|
InheritedProtocolConformanceLayout::emitRecord(Out, ScratchRecord,
|
||||||
|
abbrCode,
|
||||||
|
addDeclRef(protocol),
|
||||||
|
nominalID,
|
||||||
|
moduleOrTypeID);
|
||||||
|
if (appendInheritedConformance) {
|
||||||
|
writeConformance(protocol, conf->getInheritedConformance());
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user