Skip to content

Commit ecd830e

Browse files
committed
Rework BuiltinProtocolConformance to be more like NormalProtocolConformance.
Give BuiltinProtocolConformance a generic signature, which can be used to describe the generic parameters used within the builtin conformance, e.g., `<T1, T2, T3>` for a tuple type `(T1, T2, T3)`. Also store the conditional requirements as trailing objects, requiring them to be precomputed by whatever builds the conformances. Together, this means that builtin protocol conformances act like normal conformances with respect to conditional requirements and substitutions: they will be defined generically, then a specialized conformance will be layered on top to provide the substitutions.
1 parent 20cc067 commit ecd830e

File tree

9 files changed

+61
-78
lines changed

9 files changed

+61
-78
lines changed

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,8 @@ class ASTContext final {
10331033
/// Produce the builtin conformance for some structural type to some protocol.
10341034
BuiltinProtocolConformance *
10351035
getBuiltinConformance(Type type, ProtocolDecl *protocol,
1036-
ArrayRef<ProtocolConformanceRef> conformances);
1036+
GenericSignature genericSig,
1037+
ArrayRef<Requirement> conditionalRequirements);
10371038

10381039
/// A callback used to produce a diagnostic for an ill-formed protocol
10391040
/// conformance that was type-checked before we're actually walking the

include/swift/AST/ProtocolConformance.h

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -996,47 +996,44 @@ class InheritedProtocolConformance : public ProtocolConformance,
996996
/// A builtin conformance appears when a non-nominal type has a
997997
/// conformance that is synthesized by the implementation.
998998
class BuiltinProtocolConformance final : public RootProtocolConformance,
999-
private llvm::TrailingObjects<BuiltinProtocolConformance,
1000-
ProtocolConformanceRef> {
999+
private llvm::TrailingObjects<BuiltinProtocolConformance, Requirement> {
10011000
friend ASTContext;
10021001
friend TrailingObjects;
10031002

1004-
ProtocolDecl *protocol = nullptr;
1005-
size_t numConformances;
1003+
ProtocolDecl *protocol;
1004+
GenericSignature genericSig;
1005+
size_t numConditionalRequirements;
10061006

1007-
mutable Optional<ArrayRef<Requirement>> conditionalConformances = None;
1007+
size_t numTrailingObjects(OverloadToken<Requirement>) const {
1008+
return numConditionalRequirements;
1009+
}
10081010

10091011
BuiltinProtocolConformance(Type conformingType, ProtocolDecl *protocol,
1010-
ArrayRef<ProtocolConformanceRef> conformances);
1011-
1012-
size_t numTrailingObjects(OverloadToken<ProtocolConformanceRef>) const {
1013-
return numConformances;
1014-
}
1012+
GenericSignature genericSig,
1013+
ArrayRef<Requirement> conditionalRequirements);
10151014

10161015
public:
10171016
/// Get the protocol being conformed to.
10181017
ProtocolDecl *getProtocol() const {
10191018
return protocol;
10201019
}
10211020

1022-
/// Get the trailing conformances that this builtin conformance needs.
1023-
MutableArrayRef<ProtocolConformanceRef> getConformances() {
1024-
return {getTrailingObjects<ProtocolConformanceRef>(), numConformances};
1025-
}
1026-
1027-
/// Get the trailing conformances that this builtin conformance needs.
1028-
ArrayRef<ProtocolConformanceRef> getConformances() const {
1029-
return {getTrailingObjects<ProtocolConformanceRef>(), numConformances};
1021+
/// Retrieve the generic signature that describes the type parameters used
1022+
/// within the conforming type.
1023+
GenericSignature getGenericSignature() const {
1024+
return genericSig;
10301025
}
10311026

10321027
/// Get any requirements that must be satisfied for this conformance to apply.
10331028
Optional<ArrayRef<Requirement>>
10341029
getConditionalRequirementsIfAvailable() const {
1035-
return ArrayRef<Requirement>();
1030+
return getConditionalRequirements();
10361031
}
10371032

10381033
/// Get any requirements that must be satisfied for this conformance to apply.
1039-
ArrayRef<Requirement> getConditionalRequirements() const;
1034+
ArrayRef<Requirement> getConditionalRequirements() const {
1035+
return {getTrailingObjects<Requirement>(), numConditionalRequirements};
1036+
}
10401037

10411038
/// Get the declaration context that contains the nominal type declaration.
10421039
DeclContext *getDeclContext() const {

lib/AST/ASTContext.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,18 +2249,22 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) {
22492249

22502250
/// Produce the builtin conformance for some non-nominal to some protocol.
22512251
BuiltinProtocolConformance *
2252-
ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol,
2253-
ArrayRef<ProtocolConformanceRef> conformances) {
2252+
ASTContext::getBuiltinConformance(
2253+
Type type, ProtocolDecl *protocol,
2254+
GenericSignature genericSig,
2255+
ArrayRef<Requirement> conditionalRequirements
2256+
) {
22542257
auto key = std::make_pair(type, protocol);
22552258
AllocationArena arena = getArena(type->getRecursiveProperties());
22562259
auto &builtinConformances = getImpl().getArena(arena).BuiltinConformances;
22572260

22582261
auto &entry = builtinConformances[key];
22592262
if (!entry) {
22602263
auto size = BuiltinProtocolConformance::
2261-
totalSizeToAlloc<ProtocolConformanceRef>(conformances.size());
2264+
totalSizeToAlloc<Requirement>(conditionalRequirements.size());
22622265
auto mem = this->Allocate(size, alignof(BuiltinProtocolConformance), arena);
2263-
entry = new (mem) BuiltinProtocolConformance(type, protocol, conformances);
2266+
entry = new (mem) BuiltinProtocolConformance(
2267+
type, protocol, genericSig, conditionalRequirements);
22642268
}
22652269
return entry;
22662270
}

lib/AST/ProtocolConformance.cpp

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,10 @@ GenericSignature ProtocolConformance::getGenericSignature() const {
326326
// generic signature.
327327
return getDeclContext()->getGenericSignatureOfContext();
328328

329-
case ProtocolConformanceKind::Specialized:
330329
case ProtocolConformanceKind::Builtin:
330+
return cast<BuiltinProtocolConformance>(this)->getGenericSignature();
331+
332+
case ProtocolConformanceKind::Specialized:
331333
// If we have a specialized protocol conformance, since we do not support
332334
// currently partial specialization, we know that it cannot have any open
333335
// type variables.
@@ -1582,33 +1584,14 @@ ProtocolConformanceRef::getCanonicalConformanceRef() const {
15821584

15831585
BuiltinProtocolConformance::BuiltinProtocolConformance(
15841586
Type conformingType, ProtocolDecl *protocol,
1585-
ArrayRef<ProtocolConformanceRef> conformances) :
1586-
RootProtocolConformance(ProtocolConformanceKind::Builtin, conformingType),
1587-
protocol(protocol), numConformances(conformances.size()) {
1588-
std::uninitialized_copy(conformances.begin(), conformances.end(),
1589-
getTrailingObjects<ProtocolConformanceRef>());
1590-
}
1591-
1592-
ArrayRef<Requirement>
1593-
BuiltinProtocolConformance::getConditionalRequirements() const {
1594-
if (conditionalConformances == None) {
1595-
// Right now only tuples are builtin and have conditional conformances.
1596-
if (auto tuple = getType()->getAs<TupleType>()) {
1597-
SmallVector<Requirement, 4> requirements;
1598-
1599-
for (size_t i = 0; i != getConformances().size(); i += 1) {
1600-
auto req = Requirement(RequirementKind::Conformance,
1601-
tuple->getElement(i).getType(),
1602-
getProtocol()->getDeclaredType());
1603-
requirements.push_back(req);
1604-
}
1605-
1606-
conditionalConformances = getProtocol()->getASTContext()
1607-
.AllocateCopy(requirements);
1608-
}
1609-
}
1610-
1611-
return *conditionalConformances;
1587+
GenericSignature genericSig,
1588+
ArrayRef<Requirement> conditionalRequirements
1589+
) : RootProtocolConformance(ProtocolConformanceKind::Builtin, conformingType),
1590+
protocol(protocol), genericSig(genericSig),
1591+
numConditionalRequirements(conditionalRequirements.size()) {
1592+
std::uninitialized_copy(conditionalRequirements.begin(),
1593+
conditionalRequirements.end(),
1594+
getTrailingObjects<Requirement>());
16121595
}
16131596

16141597
// See swift/Basic/Statistic.h for declaration: this enables tracing

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6186,8 +6186,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
61866186

61876187
// This conformance may be conditional, in which case we need to consider
61886188
// those requirements as constraints too.
6189-
if (conformance.isConcrete() &&
6190-
!isa<BuiltinProtocolConformance>(conformance.getConcrete())) {
6189+
if (conformance.isConcrete()) {
61916190
unsigned index = 0;
61926191
auto *conformanceLoc = getConstraintLocator(
61936192
loc,

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ OTHER(GENERIC_PARAM_LIST, 230)
168168
OTHER(GENERIC_SIGNATURE, 231)
169169
TRAILING_INFO(GENERIC_REQUIREMENT)
170170
TRAILING_INFO(LAYOUT_REQUIREMENT)
171-
// 234 is unused
171+
OTHER(BUILTIN_PROTOCOL_CONFORMANCE, 234)
172172
OTHER(SIL_GENERIC_SIGNATURE, 235)
173173
OTHER(SUBSTITUTION_MAP, 236)
174174

@@ -198,8 +198,6 @@ OTHER(DERIVATIVE_FUNCTION_CONFIGURATION, 254)
198198

199199
OTHER(ERROR_FLAG, 255)
200200

201-
OTHER(BUILTIN_PROTOCOL_CONFORMANCE, 256)
202-
203201
#undef RECORD
204202
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL
205203
#undef RECORD_VAL

lib/Serialization/Deserialization.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,9 @@ ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
546546
case BUILTIN_PROTOCOL_CONFORMANCE: {
547547
TypeID conformingTypeID;
548548
DeclID protoID;
549-
size_t numConformances;
549+
GenericSignatureID genericSigID;
550550
BuiltinProtocolConformanceLayout::readRecord(scratch, conformingTypeID,
551-
protoID, numConformances);
551+
protoID, genericSigID);
552552

553553
Type conformingType = getType(conformingTypeID);
554554

@@ -557,17 +557,19 @@ ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
557557
return decl.takeError();
558558

559559
auto proto = cast<ProtocolDecl>(decl.get());
560-
561-
// Read the conformances.
562-
SmallVector<ProtocolConformanceRef, 4> conformances;
563-
conformances.reserve(numConformances);
564-
for (unsigned i : range(numConformances)) {
565-
(void)i;
566-
conformances.push_back(readConformance(Cursor));
567-
}
568-
569-
auto conformance = getContext().getBuiltinConformance(conformingType, proto,
570-
conformances);
560+
auto genericSig = getGenericSignatureChecked(genericSigID);
561+
if (!genericSig)
562+
return genericSig.takeError();
563+
564+
// Read the conditional requirements.
565+
SmallVector<Requirement, 4> conditionalRequirements;
566+
auto error = readGenericRequirementsChecked(
567+
conditionalRequirements, Cursor);
568+
if (error)
569+
return std::move(error);
570+
571+
auto conformance = getContext().getBuiltinConformance(
572+
conformingType, proto, *genericSig, conditionalRequirements);
571573
return ProtocolConformanceRef(conformance);
572574
}
573575

lib/Serialization/ModuleFormat.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,8 +1675,8 @@ namespace decls_block {
16751675
BUILTIN_PROTOCOL_CONFORMANCE,
16761676
TypeIDField, // the conforming type
16771677
DeclIDField, // the protocol
1678-
BCVBR<5> // the number of element conformances
1679-
// the (optional) element conformances follow
1678+
GenericSignatureIDField // the generic signature
1679+
// the (optional) conditional requirements follow
16801680
>;
16811681

16821682
// Refers to a normal protocol conformance in the given module via its id.

lib/Serialization/Serialization.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,11 +1610,10 @@ Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
16101610
unsigned abbrCode = abbrCodes[BuiltinProtocolConformanceLayout::Code];
16111611
auto typeID = addTypeRef(builtin->getType());
16121612
auto protocolID = addDeclRef(builtin->getProtocol());
1613-
BuiltinProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
1614-
typeID, protocolID,
1615-
builtin->getConformances().size());
1616-
1617-
writeConformances(builtin->getConformances(), abbrCodes);
1613+
auto genericSigID = addGenericSignatureRef(builtin->getGenericSignature());
1614+
BuiltinProtocolConformanceLayout::emitRecord(
1615+
Out, ScratchRecord, abbrCode, typeID, protocolID, genericSigID);
1616+
writeGenericRequirements(builtin->getConditionalRequirements(), abbrCodes);
16181617
break;
16191618
}
16201619
}

0 commit comments

Comments
 (0)