Skip to content

Commit b89e4d6

Browse files
authored
Merge pull request #66843 from slavapestov/variadic-type-conditional-conformance-5.9
Conditional conformances for variadic generic types [5.9]
2 parents 89245dd + 09e0c5a commit b89e4d6

15 files changed

+294
-83
lines changed

include/swift/ABI/GenericContext.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,11 @@ class TargetGenericRequirementDescriptor {
183183
return offsetof(typename std::remove_reference<decltype(*this)>::type, Param);
184184
}
185185

186-
/// Retrieve the right-hand type for a SameType or BaseClass requirement.
186+
/// Retrieve the right-hand type for a SameType, BaseClass or SameShape requirement.
187187
llvm::StringRef getMangledTypeName() const {
188188
assert(getKind() == GenericRequirementKind::SameType ||
189-
getKind() == GenericRequirementKind::BaseClass);
189+
getKind() == GenericRequirementKind::BaseClass ||
190+
getKind() == GenericRequirementKind::SameShape);
190191
return swift::Demangle::makeSymbolicMangledNameStringRef(Type.get());
191192
}
192193

include/swift/ABI/Metadata.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,6 +2596,7 @@ struct TargetProtocolConformanceDescriptor final
25962596
TargetProtocolConformanceDescriptor<Runtime>,
25972597
TargetRelativeContextPointer<Runtime>,
25982598
TargetGenericRequirementDescriptor<Runtime>,
2599+
GenericPackShapeDescriptor,
25992600
TargetResilientWitnessesHeader<Runtime>,
26002601
TargetResilientWitness<Runtime>,
26012602
TargetGenericWitnessTable<Runtime>> {
@@ -2604,6 +2605,7 @@ struct TargetProtocolConformanceDescriptor final
26042605
TargetProtocolConformanceDescriptor<Runtime>,
26052606
TargetRelativeContextPointer<Runtime>,
26062607
TargetGenericRequirementDescriptor<Runtime>,
2608+
GenericPackShapeDescriptor,
26072609
TargetResilientWitnessesHeader<Runtime>,
26082610
TargetResilientWitness<Runtime>,
26092611
TargetGenericWitnessTable<Runtime>>;
@@ -2695,12 +2697,19 @@ struct TargetProtocolConformanceDescriptor final
26952697

26962698
/// Retrieve the conditional requirements that must also be
26972699
/// satisfied
2698-
llvm::ArrayRef<GenericRequirementDescriptor>
2700+
llvm::ArrayRef<TargetGenericRequirementDescriptor<Runtime>>
26992701
getConditionalRequirements() const {
2700-
return {this->template getTrailingObjects<GenericRequirementDescriptor>(),
2702+
return {this->template getTrailingObjects<TargetGenericRequirementDescriptor<Runtime>>(),
27012703
Flags.getNumConditionalRequirements()};
27022704
}
27032705

2706+
/// Retrieve the pack shape descriptors for the conditional pack requirements.
2707+
llvm::ArrayRef<GenericPackShapeDescriptor>
2708+
getConditionalPackShapeDescriptors() const {
2709+
return {this->template getTrailingObjects<GenericPackShapeDescriptor>(),
2710+
Flags.getNumConditionalPackShapeDescriptors()};
2711+
}
2712+
27042713
/// Get the directly-referenced witness table pattern, which may also
27052714
/// serve as the witness table.
27062715
const swift::TargetWitnessTable<Runtime> *getWitnessTablePattern() const {
@@ -2759,6 +2768,10 @@ struct TargetProtocolConformanceDescriptor final
27592768
return Flags.getNumConditionalRequirements();
27602769
}
27612770

2771+
size_t numTrailingObjects(OverloadToken<GenericPackShapeDescriptor>) const {
2772+
return Flags.getNumConditionalPackShapeDescriptors();
2773+
}
2774+
27622775
size_t numTrailingObjects(OverloadToken<ResilientWitnessesHeader>) const {
27632776
return Flags.hasResilientWitnesses() ? 1 : 0;
27642777
}

include/swift/ABI/MetadataValues.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,17 +662,20 @@ class ConformanceFlags {
662662
enum : int_type {
663663
UnusedLowBits = 0x07, // historical conformance kind
664664

665-
TypeMetadataKindMask = 0x7 << 3, // 8 type reference kinds
665+
TypeMetadataKindMask = 0x7u << 3, // 8 type reference kinds
666666
TypeMetadataKindShift = 3,
667667

668-
IsRetroactiveMask = 0x01 << 6,
669-
IsSynthesizedNonUniqueMask = 0x01 << 7,
668+
IsRetroactiveMask = 0x01u << 6,
669+
IsSynthesizedNonUniqueMask = 0x01u << 7,
670670

671-
NumConditionalRequirementsMask = 0xFF << 8,
671+
NumConditionalRequirementsMask = 0xFFu << 8,
672672
NumConditionalRequirementsShift = 8,
673673

674-
HasResilientWitnessesMask = 0x01 << 16,
675-
HasGenericWitnessTableMask = 0x01 << 17,
674+
HasResilientWitnessesMask = 0x01u << 16,
675+
HasGenericWitnessTableMask = 0x01u << 17,
676+
677+
NumConditionalPackDescriptorsMask = 0xFFu << 24,
678+
NumConditionalPackDescriptorsShift = 24
676679
};
677680

678681
int_type Value;
@@ -702,6 +705,11 @@ class ConformanceFlags {
702705
| (n << NumConditionalRequirementsShift));
703706
}
704707

708+
ConformanceFlags withNumConditionalPackDescriptors(unsigned n) const {
709+
return ConformanceFlags((Value & ~NumConditionalPackDescriptorsMask)
710+
| (n << NumConditionalPackDescriptorsShift));
711+
}
712+
705713
ConformanceFlags withHasResilientWitnesses(bool hasResilientWitnesses) const {
706714
return ConformanceFlags((Value & ~HasResilientWitnessesMask)
707715
| (hasResilientWitnesses? HasResilientWitnessesMask
@@ -747,6 +755,12 @@ class ConformanceFlags {
747755
>> NumConditionalRequirementsShift;
748756
}
749757

758+
/// Retrieve the # of conditional pack shape descriptors.
759+
unsigned getNumConditionalPackShapeDescriptors() const {
760+
return (Value & NumConditionalPackDescriptorsMask)
761+
>> NumConditionalPackDescriptorsShift;
762+
}
763+
750764
/// Whether this conformance has any resilient witnesses.
751765
bool hasResilientWitnesses() const {
752766
return Value & HasResilientWitnessesMask;

lib/IRGen/Fulfillment.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,22 @@ bool FulfillmentMap::searchConformance(
228228

229229
SILWitnessTable::enumerateWitnessTableConditionalConformances(
230230
conformance, [&](unsigned index, CanType type, ProtocolDecl *protocol) {
231+
Optional<unsigned> packExpansionComponent;
232+
233+
if (auto packType = dyn_cast<PackType>(type)) {
234+
auto param =
235+
getSingletonPackExpansionParameter(packType, interestingKeys,
236+
packExpansionComponent);
237+
if (!param)
238+
return /*finished?*/ false;
239+
type = param;
240+
}
241+
231242
MetadataPath conditionalPath = path;
232243
conditionalPath.addConditionalConformanceComponent(index);
244+
if (packExpansionComponent)
245+
conditionalPath.addPackExpansionPatternComponent(*packExpansionComponent);
246+
233247
hadFulfillment |=
234248
searchWitnessTable(IGM, type, protocol, sourceIndex,
235249
std::move(conditionalPath), interestingKeys);

lib/IRGen/GenMeta.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -566,21 +566,7 @@ namespace {
566566
B.addInt(IGM.Int16Ty, shapes.size());
567567

568568
// Emit each GenericPackShapeDescriptor collected previously.
569-
for (const auto &packArg : packArgs) {
570-
// Kind
571-
B.addInt(IGM.Int16Ty, uint16_t(packArg.Kind));
572-
573-
// Index
574-
B.addInt(IGM.Int16Ty, packArg.Index);
575-
576-
// ShapeClass
577-
auto found = std::find(shapes.begin(), shapes.end(), packArg.ReducedShape);
578-
assert(found != shapes.end());
579-
B.addInt(IGM.Int16Ty, found - shapes.begin());
580-
581-
// Unused
582-
B.addInt(IGM.Int16Ty, 0);
583-
}
569+
irgen::addGenericPackShapeDescriptors(IGM, B, shapes, packArgs);
584570
}
585571

586572
uint8_t getVersion() {
@@ -6558,6 +6544,27 @@ GenericArgumentMetadata irgen::addGenericRequirements(
65586544
return metadata;
65596545
}
65606546

6547+
void irgen::addGenericPackShapeDescriptors(IRGenModule &IGM,
6548+
ConstantStructBuilder &B,
6549+
ArrayRef<CanType> shapes,
6550+
ArrayRef<GenericPackArgument> packArgs) {
6551+
for (const auto &packArg : packArgs) {
6552+
// Kind
6553+
B.addInt(IGM.Int16Ty, uint16_t(packArg.Kind));
6554+
6555+
// Index
6556+
B.addInt(IGM.Int16Ty, packArg.Index);
6557+
6558+
// ShapeClass
6559+
auto found = std::find(shapes.begin(), shapes.end(), packArg.ReducedShape);
6560+
assert(found != shapes.end());
6561+
B.addInt(IGM.Int16Ty, found - shapes.begin());
6562+
6563+
// Unused
6564+
B.addInt(IGM.Int16Ty, 0);
6565+
}
6566+
}
6567+
65616568
//===----------------------------------------------------------------------===//
65626569
// Other metadata.
65636570
//===----------------------------------------------------------------------===//

lib/IRGen/GenMeta.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ namespace irgen {
239239
GenericSignature sig,
240240
ArrayRef<Requirement> requirements);
241241

242+
/// Add generic pack shape descriptors to the given constant struct builder.
243+
///
244+
/// These appear in generic type metadata, and conformance descriptors with
245+
/// conditional pack requirements.
246+
void addGenericPackShapeDescriptors(IRGenModule &IGM,
247+
ConstantStructBuilder &B,
248+
ArrayRef<CanType> shapes,
249+
ArrayRef<GenericPackArgument> packArgs);
250+
242251
llvm::GlobalValue *emitAsyncFunctionPointer(IRGenModule &IGM,
243252
llvm::Function *function,
244253
LinkEntity entity,

lib/IRGen/GenProto.cpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,10 @@ namespace {
19421942
ConformanceDescription Description;
19431943
ConformanceFlags Flags;
19441944

1945+
using PlaceholderPosition =
1946+
ConstantAggregateBuilderBase::PlaceholderPosition;
1947+
Optional<PlaceholderPosition> FlagsPP;
1948+
19451949
public:
19461950
ProtocolConformanceDescriptorBuilder(
19471951
IRGenModule &IGM,
@@ -1960,6 +1964,11 @@ namespace {
19601964
addResilientWitnesses();
19611965
addGenericWitnessTable();
19621966

1967+
// We fill the flags last, since we continue filling them in
1968+
// after the call to addFlags() deposits the placeholder.
1969+
B.fillPlaceholderWithInt(*FlagsPP, IGM.Int32Ty,
1970+
Flags.getIntValue());
1971+
19631972
B.suggestType(IGM.ProtocolConformanceDescriptorTy);
19641973
}
19651974

@@ -1981,13 +1990,6 @@ namespace {
19811990
}
19821991

19831992
void addWitnessTable() {
1984-
// Note the number of conditional requirements.
1985-
unsigned numConditional = 0;
1986-
if (auto normal = dyn_cast<NormalProtocolConformance>(Conformance)) {
1987-
numConditional = normal->getConditionalRequirements().size();
1988-
}
1989-
Flags = Flags.withNumConditionalRequirements(numConditional);
1990-
19911993
// Relative reference to the witness table.
19921994
B.addRelativeAddressOrNull(Description.pattern);
19931995
}
@@ -2001,13 +2003,9 @@ namespace {
20012003
Flags = Flags.withIsRetroactive(false)
20022004
.withIsSynthesizedNonUnique(false);
20032005
}
2004-
Flags = Flags.withHasResilientWitnesses(
2005-
!Description.resilientWitnesses.empty());
2006-
Flags =
2007-
Flags.withHasGenericWitnessTable(Description.requiresSpecialization);
20082006

2009-
// Add the flags.
2010-
B.addInt32(Flags.getIntValue());
2007+
// Add a placeholder for the flags.
2008+
FlagsPP = B.addPlaceholderWithSize(IGM.Int32Ty);
20112009
}
20122010

20132011
void addContext() {
@@ -2025,19 +2023,42 @@ namespace {
20252023

20262024
void addConditionalRequirements() {
20272025
auto normal = dyn_cast<NormalProtocolConformance>(Conformance);
2028-
if (!normal || normal->getConditionalRequirements().empty())
2026+
if (!normal)
20292027
return;
20302028

2031-
auto nominal = normal->getType()->getAnyNominal();
2032-
irgen::addGenericRequirements(IGM, B,
2033-
nominal->getGenericSignatureOfContext(),
2034-
normal->getConditionalRequirements());
2029+
auto condReqs = normal->getConditionalRequirements();
2030+
if (condReqs.empty())
2031+
return;
2032+
2033+
Flags = Flags.withNumConditionalRequirements(condReqs.size());
2034+
2035+
auto nominal = normal->getDeclContext()->getSelfNominalTypeDecl();
2036+
auto sig = nominal->getGenericSignatureOfContext();
2037+
auto metadata = irgen::addGenericRequirements(IGM, B, sig, condReqs);
2038+
2039+
Flags = Flags.withNumConditionalPackDescriptors(
2040+
metadata.GenericPackArguments.size());
2041+
2042+
// Collect the shape classes from the nominal type's generic signature.
2043+
sig->forEachParam([&](GenericTypeParamType *param, bool canonical) {
2044+
if (canonical && param->isParameterPack()) {
2045+
auto reducedShape = sig->getReducedShape(param)->getCanonicalType();
2046+
if (reducedShape->isEqual(param))
2047+
metadata.ShapeClasses.push_back(reducedShape);
2048+
}
2049+
});
2050+
2051+
irgen::addGenericPackShapeDescriptors(
2052+
IGM, B, metadata.ShapeClasses,
2053+
metadata.GenericPackArguments);
20352054
}
20362055

20372056
void addResilientWitnesses() {
20382057
if (Description.resilientWitnesses.empty())
20392058
return;
20402059

2060+
Flags = Flags.withHasResilientWitnesses(true);
2061+
20412062
// TargetResilientWitnessesHeader
20422063
ArrayRef<llvm::Constant *> witnesses = Description.resilientWitnesses;
20432064
B.addInt32(witnesses.size());
@@ -2098,6 +2119,8 @@ namespace {
20982119
if (!Description.requiresSpecialization)
20992120
return;
21002121

2122+
Flags = Flags.withHasGenericWitnessTable(true);
2123+
21012124
// WitnessTableSizeInWords
21022125
B.addInt(IGM.Int16Ty, Description.witnessTableSize);
21032126
// WitnessTablePrivateSizeInWordsAndRequiresInstantiation

lib/IRGen/LocalTypeData.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,18 +473,24 @@ void IRGenFunction::bindLocalTypeDataFromSelfWitnessTable(
473473
SILWitnessTable::enumerateWitnessTableConditionalConformances(
474474
conformance,
475475
[&](unsigned index, CanType type, ProtocolDecl *proto) {
476-
auto archetype = getTypeInContext(type);
477-
if (isa<ArchetypeType>(archetype)) {
476+
if (auto packType = dyn_cast<PackType>(type)) {
477+
if (auto expansion = packType.unwrapSingletonPackExpansion())
478+
type = expansion.getPatternType();
479+
}
480+
481+
type = getTypeInContext(type);
482+
483+
if (isa<ArchetypeType>(type)) {
478484
WitnessIndex wIndex(privateWitnessTableIndexToTableOffset(index),
479485
/*prefix*/ false);
480486

481487
auto table = loadConditionalConformance(*this ,selfTable,
482488
wIndex.forProtocolWitnessTable());
483489
table = Builder.CreateBitCast(table, IGM.WitnessTablePtrTy);
484-
setProtocolWitnessTableName(IGM, table, archetype, proto);
490+
setProtocolWitnessTableName(IGM, table, type, proto);
485491

486492
setUnscopedLocalTypeData(
487-
archetype,
493+
type,
488494
LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
489495
table);
490496
}

0 commit comments

Comments
 (0)