Skip to content

Commit 74091fb

Browse files
committed
[AST] Store and serialize a protocol's requirement signature.
This is the "canonical" representation of the type-level requirements of a protocol, and we intend to use it pervasively in the compiler.
1 parent a834780 commit 74091fb

File tree

6 files changed

+41
-9
lines changed

6 files changed

+41
-9
lines changed

include/swift/AST/Decl.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3392,6 +3392,10 @@ class ProtocolDecl : public NominalTypeDecl {
33923392

33933393
llvm::DenseMap<ValueDecl *, Witness> DefaultWitnesses;
33943394

3395+
/// The generic signature representing exactly the new requirements introduced
3396+
/// by this protocol.
3397+
GenericSignature *RequirementSignature = nullptr;
3398+
33953399
/// True if the protocol has requirements that cannot be satisfied (e.g.
33963400
/// because they could not be imported from Objective-C).
33973401
unsigned HasMissingRequirements : 1;
@@ -3585,7 +3589,17 @@ class ProtocolDecl : public NominalTypeDecl {
35853589
/// for associated types that are mentioned literally in this
35863590
/// decl. Requirements implied via inheritance are not mentioned, nor is the
35873591
/// conformance of Self to this protocol.
3588-
GenericSignature *getRequirementSignature();
3592+
GenericSignature *getRequirementSignature() const {
3593+
assert(RequirementSignature &&
3594+
"getting requirement signature before computing it");
3595+
return RequirementSignature;
3596+
}
3597+
3598+
void computeRequirementSignature();
3599+
3600+
void setRequirementSignature(GenericSignature *sig) {
3601+
RequirementSignature = sig;
3602+
}
35893603

35903604
// Implement isa/cast/dyncast/etc.
35913605
static bool classof(const Decl *D) {

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 311; // Last change: unmanaged autorelease value
57+
const uint16_t VERSION_MINOR = 312; // Last change: serialize requirement signatures
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/AST/Decl.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,16 +3005,22 @@ void ProtocolDecl::createGenericParamsIfMissing() {
30053005
setGenericParams(createGenericParams(this));
30063006
}
30073007

3008-
GenericSignature *ProtocolDecl::getRequirementSignature() {
3008+
void ProtocolDecl::computeRequirementSignature() {
3009+
assert(!RequirementSignature && "already computed requirement signature");
3010+
30093011
auto module = getParentModule();
30103012

30113013
auto genericSig = getGenericSignature();
30123014
// The signature should look like <Self where Self : ThisProtocol>, and we
30133015
// reuse the two parts of it because the parameter and the requirement are
30143016
// exactly what we need.
3015-
assert(genericSig->getGenericParams().size() == 1 &&
3016-
genericSig->getRequirements().size() == 1 &&
3017-
"getRequirementSignature with unexpected generic signature");
3017+
auto validSig = genericSig->getGenericParams().size() == 1 &&
3018+
genericSig->getRequirements().size() == 1;
3019+
if (!validSig) {
3020+
// This doesn't look like a protocol we can handle, so some other error must
3021+
// have occured (usually a protocol nested within another declaration)
3022+
return;
3023+
}
30183024

30193025
auto selfType = genericSig->getGenericParams()[0];
30203026
auto requirement = genericSig->getRequirements()[0];
@@ -3027,7 +3033,7 @@ GenericSignature *ProtocolDecl::getRequirementSignature() {
30273033
builder.addRequirement(requirement, source);
30283034
builder.finalize(SourceLoc(), { selfType });
30293035

3030-
return builder.getGenericSignature();
3036+
RequirementSignature = builder.getGenericSignature();
30313037
}
30323038

30333039
/// Returns the default witness for a requirement, or nullptr if there is

lib/Sema/TypeCheckDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7080,6 +7080,8 @@ void TypeChecker::validateDecl(ValueDecl *D) {
70807080
markAsObjC(*this, proto, isObjC);
70817081
}
70827082

7083+
proto->computeRequirementSignature();
7084+
70837085
ValidatedTypes.insert(proto);
70847086
break;
70857087
}

lib/Serialization/Deserialization.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,8 +3059,16 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
30593059

30603060
handleInherited(proto, rawProtocolAndInheritedIDs.slice(numProtocols));
30613061

3062-
if (auto genericParams = maybeReadGenericParams(DC))
3063-
proto->setGenericParams(genericParams);
3062+
auto genericParams = maybeReadGenericParams(DC);
3063+
assert(genericParams && "protocol with no generic parameters?");
3064+
proto->setGenericParams(genericParams);
3065+
3066+
SmallVector<Requirement, 4> requirements;
3067+
readGenericRequirements(requirements, DeclTypeCursor);
3068+
3069+
auto signature = GenericSignature::get(
3070+
proto->getGenericEnvironment()->getGenericParams(), requirements);
3071+
proto->setRequirementSignature(signature);
30643072

30653073
if (isImplicit)
30663074
proto->setImplicit();

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2661,6 +2661,8 @@ void Serializer::writeDecl(const Decl *D) {
26612661
protocolsAndInherited);
26622662

26632663
writeGenericParams(proto->getGenericParams());
2664+
writeGenericRequirements(
2665+
proto->getRequirementSignature()->getRequirements(), DeclTypeAbbrCodes);
26642666
writeMembers(proto->getMembers(), true);
26652667
writeDefaultWitnessTable(proto, DeclTypeAbbrCodes);
26662668
break;

0 commit comments

Comments
 (0)