Skip to content

Commit dc4daee

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. (cherry picked from commit ecd830e)
1 parent 46d3275 commit dc4daee

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
@@ -1014,7 +1014,8 @@ class ASTContext final {
10141014
/// Produce the builtin conformance for some structural type to some protocol.
10151015
BuiltinProtocolConformance *
10161016
getBuiltinConformance(Type type, ProtocolDecl *protocol,
1017-
ArrayRef<ProtocolConformanceRef> conformances);
1017+
GenericSignature genericSig,
1018+
ArrayRef<Requirement> conditionalRequirements);
10181019

10191020
/// A callback used to produce a diagnostic for an ill-formed protocol
10201021
/// 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
@@ -2195,18 +2195,22 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) {
21952195

21962196
/// Produce the builtin conformance for some non-nominal to some protocol.
21972197
BuiltinProtocolConformance *
2198-
ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol,
2199-
ArrayRef<ProtocolConformanceRef> conformances) {
2198+
ASTContext::getBuiltinConformance(
2199+
Type type, ProtocolDecl *protocol,
2200+
GenericSignature genericSig,
2201+
ArrayRef<Requirement> conditionalRequirements
2202+
) {
22002203
auto key = std::make_pair(type, protocol);
22012204
AllocationArena arena = getArena(type->getRecursiveProperties());
22022205
auto &builtinConformances = getImpl().getArena(arena).BuiltinConformances;
22032206

22042207
auto &entry = builtinConformances[key];
22052208
if (!entry) {
22062209
auto size = BuiltinProtocolConformance::
2207-
totalSizeToAlloc<ProtocolConformanceRef>(conformances.size());
2210+
totalSizeToAlloc<Requirement>(conditionalRequirements.size());
22082211
auto mem = this->Allocate(size, alignof(BuiltinProtocolConformance), arena);
2209-
entry = new (mem) BuiltinProtocolConformance(type, protocol, conformances);
2212+
entry = new (mem) BuiltinProtocolConformance(
2213+
type, protocol, genericSig, conditionalRequirements);
22102214
}
22112215
return entry;
22122216
}

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.
@@ -1580,33 +1582,14 @@ ProtocolConformanceRef::getCanonicalConformanceRef() const {
15801582

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

16121595
// 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
@@ -6160,8 +6160,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
61606160

61616161
// This conformance may be conditional, in which case we need to consider
61626162
// those requirements as constraints too.
6163-
if (conformance.isConcrete() &&
6164-
!isa<BuiltinProtocolConformance>(conformance.getConcrete())) {
6163+
if (conformance.isConcrete()) {
61656164
unsigned index = 0;
61666165
auto *conformanceLoc = getConstraintLocator(
61676166
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
@@ -1666,8 +1666,8 @@ namespace decls_block {
16661666
BUILTIN_PROTOCOL_CONFORMANCE,
16671667
TypeIDField, // the conforming type
16681668
DeclIDField, // the protocol
1669-
BCVBR<5> // the number of element conformances
1670-
// the (optional) element conformances follow
1669+
GenericSignatureIDField // the generic signature
1670+
// the (optional) conditional requirements follow
16711671
>;
16721672

16731673
// 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
@@ -1579,11 +1579,10 @@ Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
15791579
unsigned abbrCode = abbrCodes[BuiltinProtocolConformanceLayout::Code];
15801580
auto typeID = addTypeRef(builtin->getType());
15811581
auto protocolID = addDeclRef(builtin->getProtocol());
1582-
BuiltinProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
1583-
typeID, protocolID,
1584-
builtin->getConformances().size());
1585-
1586-
writeConformances(builtin->getConformances(), abbrCodes);
1582+
auto genericSigID = addGenericSignatureRef(builtin->getGenericSignature());
1583+
BuiltinProtocolConformanceLayout::emitRecord(
1584+
Out, ScratchRecord, abbrCode, typeID, protocolID, genericSigID);
1585+
writeGenericRequirements(builtin->getConditionalRequirements(), abbrCodes);
15871586
break;
15881587
}
15891588
}

0 commit comments

Comments
 (0)