Serialize the list of inherited types for all nominal types.

This provides better AST fidelity through module files and further
reduces our dependencies on storing a list of protocols on nominal
type declarations.

Swift SVN r31345
This commit is contained in:
Doug Gregor
2015-08-19 21:10:45 +00:00
parent dd68b9fc59
commit 83cb1e69bb
6 changed files with 134 additions and 69 deletions

View File

@@ -51,7 +51,7 @@ const uint16_t VERSION_MAJOR = 0;
/// To ensure that two separate changes don't silently get merged into one
/// in source control, you should also update the comment to briefly
/// describe what change you made.
const uint16_t VERSION_MINOR = 214; // Last change: extension inherited list
const uint16_t VERSION_MINOR = 215; // Last change: nominal inherited lists
using DeclID = Fixnum<31>;
using DeclIDField = BCFixed<31>;
@@ -773,7 +773,8 @@ namespace decls_block {
DeclContextIDField, // context decl
BCFixed<1>, // implicit flag
AccessibilityKindField, // accessibility
BCArray<DeclIDField> // protocols
BCVBR<4>, // number of protocols
BCArray<DeclIDField> // protocols and inherited types
// Trailed by the generic parameters (if any), the members record, and
// finally conformance info (if any).
>;
@@ -785,7 +786,8 @@ namespace decls_block {
BCFixed<1>, // implicit flag
TypeIDField, // raw type
AccessibilityKindField, // accessibility
BCArray<DeclIDField> // protocols
BCVBR<4>, // number of protocols
BCArray<DeclIDField> // protocols and inherited types
// Trailed by the generic parameters (if any), the members record, and
// finally conformance info (if any).
>;
@@ -800,7 +802,8 @@ namespace decls_block {
BCFixed<1>, // foreign
TypeIDField, // superclass
AccessibilityKindField, // accessibility
BCArray<DeclIDField> // protocols
BCVBR<4>, // number of protocols
BCArray<DeclIDField> // protocols and inherited types
// Trailed by the generic parameters (if any), the members record, and
// finally conformance info (if any).
>;
@@ -813,7 +816,8 @@ namespace decls_block {
BCFixed<1>, // class-bounded?
BCFixed<1>, // objc?
AccessibilityKindField, // accessibility
BCArray<DeclIDField> // protocols
BCVBR<4>, // number of protocols
BCArray<DeclIDField> // protocols and inherited types
// Trailed by the generic parameters (if any) and the members record
>;

View File

@@ -999,17 +999,11 @@ void PrintAST::printInherited(const Decl *decl,
void PrintAST::printInherited(const NominalTypeDecl *decl,
bool explicitClass) {
printInherited(
decl, decl->getInherited(),
decl->getLocalProtocols(ConformanceLookupKind::OnlyExplicit), nullptr,
explicitClass);
printInherited(decl, decl->getInherited(), { }, nullptr, explicitClass);
}
void PrintAST::printInherited(const EnumDecl *decl) {
printInherited(
decl, decl->getInherited(),
decl->getLocalProtocols(ConformanceLookupKind::OnlyExplicit),
decl->getRawType());
printInherited(decl, decl->getInherited(), { });
}
void PrintAST::printInherited(const ExtensionDecl *decl) {
@@ -1280,10 +1274,7 @@ void PrintAST::visitClassDecl(ClassDecl *decl) {
printNominalDeclName(decl);
});
printInherited(
decl, decl->getInherited(),
decl->getLocalProtocols(ConformanceLookupKind::OnlyExplicit),
decl->getSuperclass());
printInherited(decl);
if (Options.TypeDefinitions) {
printMembers(decl->getMembers());

View File

@@ -1616,6 +1616,19 @@ namespace {
return CD;
}
template<unsigned N>
void populateInheritedTypes(NominalTypeDecl *nominal,
ProtocolDecl * const (&protocols)[N]) {
TypeLoc inheritedTypes[N];
for_each(MutableArrayRef<TypeLoc>(inheritedTypes),
ArrayRef<ProtocolDecl *>(protocols),
[](TypeLoc &tl, ProtocolDecl *proto) {
tl = TypeLoc::withoutLoc(proto->getDeclaredType());
});
nominal->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
nominal->setCheckedInheritanceClause();
}
NominalTypeDecl *importAsOptionSetType(DeclContext *dc,
Identifier name,
const clang::EnumDecl *decl) {
@@ -1672,6 +1685,7 @@ namespace {
ProtocolDecl *protocols[]
= {cxt.getProtocol(KnownProtocolKind::OptionSetType)};
structDecl->setProtocols(Impl.SwiftContext.AllocateCopy(protocols));
populateInheritedTypes(structDecl, protocols);
structDecl->addMember(labeledValueConstructor);
structDecl->addMember(patternBinding);
@@ -1731,6 +1745,7 @@ namespace {
= {cxt.getProtocol(KnownProtocolKind::RawRepresentable)};
auto protoList = Impl.SwiftContext.AllocateCopy(protocols);
structDecl->setProtocols(protoList);
populateInheritedTypes(structDecl, protocols);
// Note that this is a raw representable type.
structDecl->getAttrs().add(
@@ -1823,7 +1838,11 @@ namespace {
};
auto protoList = Impl.SwiftContext.AllocateCopy(protocols);
enumDecl->setProtocols(protoList);
enumDecl->setInherited(
Impl.SwiftContext.AllocateCopy(
llvm::makeArrayRef(TypeLoc::withoutLoc(underlyingType))));
enumDecl->setCheckedInheritanceClause();
// Provide custom implementations of the init(rawValue:) and rawValue
// conversions that just do a bitcast. We can't reliably filter a
// C enum without additional knowledge that the type has no

View File

@@ -1827,6 +1827,32 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
PrivateDiscriminatorRAII privateDiscriminatorRAII{*this, declOrOffset};
LocalDiscriminatorRAII localDiscriminatorRAII(declOrOffset);
// Local function that handles the list of protocols to which a nominal type
// conforms as well as the "inherited" list as written in the source.
auto handleProtocolsAndInherited
= [&](NominalTypeDecl *nominal, unsigned numProtocols,
ArrayRef<uint64_t> rawProtocolAndInheritedIDs) {
auto protocols = ctx.Allocate<ProtocolDecl *>(numProtocols);
for_each(protocols, rawProtocolAndInheritedIDs.slice(0, numProtocols),
[this](ProtocolDecl *&p, uint64_t rawID) {
p = cast<ProtocolDecl>(getDecl(rawID));
});
if (auto proto = dyn_cast<ProtocolDecl>(nominal)) {
proto->setDirectlyInheritedProtocols(protocols);
} else {
nominal->setProtocols(protocols);
}
unsigned numInherited = rawProtocolAndInheritedIDs.size() - numProtocols;
auto inheritedTypes = ctx.Allocate<TypeLoc>(numInherited);
for (unsigned i = 0; i != numInherited; ++i) {
uint64_t rawID = rawProtocolAndInheritedIDs[i + numProtocols];
inheritedTypes[i] = TypeLoc::withoutLoc(getType(rawID));
}
nominal->setInherited(inheritedTypes);
nominal->setCheckedInheritanceClause();
};
while (true) {
if (entry.Kind != llvm::BitstreamEntry::Record) {
// We don't know how to serialize decls represented by sub-blocks.
@@ -2172,11 +2198,13 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
DeclContextID contextID;
bool isImplicit;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> rawProtocolIDs;
unsigned numProtocols;
ArrayRef<uint64_t> rawProtocolAndInheritedIDs;
decls_block::StructLayout::readRecord(scratch, nameID, contextID,
isImplicit, rawAccessLevel,
rawProtocolIDs);
numProtocols,
rawProtocolAndInheritedIDs);
auto DC = getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -2217,21 +2245,16 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
theStruct->computeType();
auto protocols = ctx.Allocate<ProtocolDecl *>(rawProtocolIDs.size());
for_each(protocols, rawProtocolIDs, [this](ProtocolDecl *&p,
uint64_t rawID) {
p = cast<ProtocolDecl>(getDecl(rawID));
});
theStruct->setProtocols(protocols);
handleProtocolsAndInherited(theStruct, numProtocols,
rawProtocolAndInheritedIDs);
theStruct->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
skipRecord(DeclTypeCursor, decls_block::MEMBERS);
theStruct->setConformanceLoader(
this,
encodeLazyConformanceContextData(protocols.size(),
encodeLazyConformanceContextData(numProtocols,
DeclTypeCursor.GetCurrentBitNo()));
theStruct->setCheckedInheritanceClause();
break;
}
@@ -2614,11 +2637,14 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
DeclContextID contextID;
bool isImplicit, isClassBounded, isObjC;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> protocolIDs;
unsigned numProtocols;
ArrayRef<uint64_t> rawProtocolAndInheritedIDs;
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
isImplicit, isClassBounded, isObjC,
rawAccessLevel, protocolIDs);
rawAccessLevel,
numProtocols,
rawProtocolAndInheritedIDs);
auto DC = getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -2658,15 +2684,10 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
proto->setImplicit();
proto->computeType();
// Deserialize the list of protocols.
auto inherited = ctx.Allocate<ProtocolDecl *>(protocolIDs.size());
for_each(inherited, protocolIDs, [this](ProtocolDecl *&p, uint64_t rawID) {
p = cast<ProtocolDecl>(getDecl(rawID));
});
proto->setDirectlyInheritedProtocols(inherited);
handleProtocolsAndInherited(proto, numProtocols,
rawProtocolAndInheritedIDs);
proto->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
proto->setCheckedInheritanceClause();
proto->setCircularityCheck(CircularityCheck::Checked);
break;
}
@@ -2748,12 +2769,14 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
bool isImplicit, isObjC, requiresStoredPropertyInits, foreign;
TypeID superclassID;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> rawProtocolIDs;
unsigned numProtocols;
ArrayRef<uint64_t> rawProtocolAndInheritedIDs;
decls_block::ClassLayout::readRecord(scratch, nameID, contextID,
isImplicit, isObjC,
requiresStoredPropertyInits,
foreign, superclassID, rawAccessLevel,
rawProtocolIDs);
numProtocols,
rawProtocolAndInheritedIDs);
auto DC = getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -2799,22 +2822,17 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
}
theClass->computeType();
auto protocols = ctx.Allocate<ProtocolDecl *>(rawProtocolIDs.size());
for_each(protocols, rawProtocolIDs, [this](ProtocolDecl *&p,
uint64_t rawID) {
p = cast<ProtocolDecl>(getDecl(rawID));
});
theClass->setProtocols(protocols);
handleProtocolsAndInherited(theClass, numProtocols,
rawProtocolAndInheritedIDs);
theClass->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
theClass->setHasDestructor();
skipRecord(DeclTypeCursor, decls_block::MEMBERS);
theClass->setConformanceLoader(
this,
encodeLazyConformanceContextData(protocols.size(),
encodeLazyConformanceContextData(numProtocols,
DeclTypeCursor.GetCurrentBitNo()));
theClass->setCheckedInheritanceClause();
theClass->setCircularityCheck(CircularityCheck::Checked);
break;
}
@@ -2825,11 +2843,13 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
bool isImplicit;
TypeID rawTypeID;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> rawProtocolIDs;
unsigned numProtocols;
ArrayRef<uint64_t> rawProtocolAndInheritedIDs;
decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
isImplicit, rawTypeID, rawAccessLevel,
rawProtocolIDs);
numProtocols,
rawProtocolAndInheritedIDs);
auto DC = getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -2871,18 +2891,14 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
theEnum->computeType();
auto protocols = ctx.Allocate<ProtocolDecl *>(rawProtocolIDs.size());
for_each(protocols, rawProtocolIDs, [this](ProtocolDecl *&p,
uint64_t rawID) {
p = cast<ProtocolDecl>(getDecl(rawID));
});
theEnum->setProtocols(protocols);
handleProtocolsAndInherited(theEnum, numProtocols,
rawProtocolAndInheritedIDs);
theEnum->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
skipRecord(DeclTypeCursor, decls_block::MEMBERS);
theEnum->setConformanceLoader(
this,
encodeLazyConformanceContextData(protocols.size(),
encodeLazyConformanceContextData(numProtocols,
DeclTypeCursor.GetCurrentBitNo()));
theEnum->setCheckedInheritanceClause();

View File

@@ -2147,9 +2147,12 @@ void Serializer::writeDecl(const Decl *D) {
auto contextID = addDeclContextRef(theStruct->getDeclContext());
SmallVector<DeclID, 8> protocols;
SmallVector<DeclID, 8> protocolsAndInherited;
for (auto proto : theStruct->getLocalProtocols())
protocols.push_back(addDeclRef(proto));
protocolsAndInherited.push_back(addDeclRef(proto));
unsigned numProtocols = protocolsAndInherited.size();
for (auto inherited : theStruct->getInherited())
protocolsAndInherited.push_back(addTypeRef(inherited.getType()));
uint8_t rawAccessLevel =
getRawStableAccessibility(theStruct->getFormalAccess());
@@ -2160,7 +2163,8 @@ void Serializer::writeDecl(const Decl *D) {
contextID,
theStruct->isImplicit(),
rawAccessLevel,
protocols);
numProtocols,
protocolsAndInherited);
writeGenericParams(theStruct->getGenericParams(), DeclTypeAbbrCodes);
@@ -2179,9 +2183,12 @@ void Serializer::writeDecl(const Decl *D) {
auto contextID = addDeclContextRef(theEnum->getDeclContext());
SmallVector<DeclID, 8> protocols;
SmallVector<DeclID, 8> protocolsAndInherited;
for (auto proto : theEnum->getLocalProtocols())
protocols.push_back(addDeclRef(proto));
protocolsAndInherited.push_back(addDeclRef(proto));
unsigned numProtocols = protocolsAndInherited.size();
for (auto inherited : theEnum->getInherited())
protocolsAndInherited.push_back(addTypeRef(inherited.getType()));
uint8_t rawAccessLevel =
getRawStableAccessibility(theEnum->getFormalAccess());
@@ -2193,7 +2200,8 @@ void Serializer::writeDecl(const Decl *D) {
theEnum->isImplicit(),
addTypeRef(theEnum->getRawType()),
rawAccessLevel,
protocols);
numProtocols,
protocolsAndInherited);
writeGenericParams(theEnum->getGenericParams(), DeclTypeAbbrCodes);
writeRequirements(theEnum->getGenericRequirements());
@@ -2211,9 +2219,12 @@ void Serializer::writeDecl(const Decl *D) {
auto contextID = addDeclContextRef(theClass->getDeclContext());
SmallVector<DeclID, 8> protocols;
SmallVector<DeclID, 8> protocolsAndInherited;
for (auto proto : theClass->getLocalProtocols())
protocols.push_back(addDeclRef(proto));
protocolsAndInherited.push_back(addDeclRef(proto));
unsigned numProtocols = protocolsAndInherited.size();
for (auto inherited : theClass->getInherited())
protocolsAndInherited.push_back(addTypeRef(inherited.getType()));
uint8_t rawAccessLevel =
getRawStableAccessibility(theClass->getFormalAccess());
@@ -2228,7 +2239,8 @@ void Serializer::writeDecl(const Decl *D) {
theClass->isForeign(),
addTypeRef(theClass->getSuperclass()),
rawAccessLevel,
protocols);
numProtocols,
protocolsAndInherited);
writeGenericParams(theClass->getGenericParams(), DeclTypeAbbrCodes);
writeRequirements(theClass->getGenericRequirements());
@@ -2247,9 +2259,12 @@ void Serializer::writeDecl(const Decl *D) {
auto contextID = addDeclContextRef(proto->getDeclContext());
SmallVector<DeclID, 8> protocols;
SmallVector<DeclID, 8> protocolsAndInherited;
for (auto proto : proto->getInheritedProtocols(nullptr))
protocols.push_back(addDeclRef(proto));
protocolsAndInherited.push_back(addDeclRef(proto));
unsigned numProtocols = protocolsAndInherited.size();
for (auto inherited : proto->getInherited())
protocolsAndInherited.push_back(addTypeRef(inherited.getType()));
uint8_t rawAccessLevel =
getRawStableAccessibility(proto->getFormalAccess());
@@ -2263,7 +2278,8 @@ void Serializer::writeDecl(const Decl *D) {
->requiresClass(),
proto->isObjC(),
rawAccessLevel,
protocols);
numProtocols,
protocolsAndInherited);
writeGenericParams(proto->getGenericParams(), DeclTypeAbbrCodes);
writeRequirements(proto->getGenericRequirements());

View File

@@ -781,6 +781,11 @@ struct StructWithInheritance1 : FooProtocol {}
struct StructWithInheritance2 : FooProtocol, BarProtocol {}
// PASS_ONE_LINE-DAG: {{^}}struct StructWithInheritance2 : FooProtocol, BarProtocol {{{$}}
struct StructWithInheritance3 : QuxProtocol, SubFooProtocol {
typealias Qux = Int
}
// PASS_ONE_LINE-DAG: {{^}}struct StructWithInheritance3 : QuxProtocol, SubFooProtocol {{{$}}
//===---
//===--- Inheritance list in classes.
//===---
@@ -803,6 +808,11 @@ class ClassWithInheritance4 : FooClass, FooProtocol {}
class ClassWithInheritance5 : FooClass, FooProtocol, BarProtocol {}
// PASS_ONE_LINE-DAG: {{^}}class ClassWithInheritance5 : FooClass, FooProtocol, BarProtocol {{{$}}
class ClassWithInheritance6 : QuxProtocol, SubFooProtocol {
typealias Qux = Int
}
// PASS_ONE_LINE-DAG: {{^}}class ClassWithInheritance6 : QuxProtocol, SubFooProtocol {{{$}}
//===---
//===--- Inheritance list in enums.
//===---
@@ -822,6 +832,11 @@ enum EnumDeclWithUnderlyingType1 : Int { case X }
enum EnumDeclWithUnderlyingType2 : Int, FooProtocol { case X }
// PASS_ONE_LINE-DAG: {{^}}enum EnumDeclWithUnderlyingType2 : Int, FooProtocol {{{$}}
enum EnumWithInheritance3 : QuxProtocol, SubFooProtocol {
typealias Qux = Int
}
// PASS_ONE_LINE-DAG: {{^}}enum EnumWithInheritance3 : QuxProtocol, SubFooProtocol {{{$}}
//===---
//===--- Inheritance list in protocols.
//===---
@@ -832,9 +847,13 @@ protocol ProtocolWithoutInheritance1 {}
protocol ProtocolWithInheritance1 : FooProtocol {}
// PASS_ONE_LINE-DAG: {{^}}protocol ProtocolWithInheritance1 : FooProtocol {{{$}}
protocol ProtocolWithInheritance2 : FooProtocol, BarProtocol {}
protocol ProtocolWithInheritance2 : FooProtocol, BarProtocol { }
// PASS_ONE_LINE-DAG: {{^}}protocol ProtocolWithInheritance2 : FooProtocol, BarProtocol {{{$}}
protocol ProtocolWithInheritance3 : QuxProtocol, SubFooProtocol {
}
// PASS_ONE_LINE-DAG: {{^}}protocol ProtocolWithInheritance3 : QuxProtocol, SubFooProtocol {{{$}}
//===---
//===--- Inheritance list in extensions
//===---