Skip to content

Commit aa1aad1

Browse files
committed
IRGen: Fix binding element archetypes when we have concrete pack conformances
1 parent 5995990 commit aa1aad1

File tree

2 files changed

+41
-24
lines changed

2 files changed

+41
-24
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ static llvm::Value *tryGetLocalPackTypeData(IRGenFunction &IGF,
6969
return wtable;
7070

7171
if (auto packArchetypeType = getForwardedPackArchetypeType(packType)) {
72+
// Also unwrap the pack conformance, if there is one.
73+
if (localDataKind.isPackProtocolConformance()) {
74+
localDataKind = LocalTypeDataKind::forProtocolWitnessTable(
75+
localDataKind.getPackProtocolConformance()
76+
->getPatternConformances()[0]);
77+
}
78+
7279
if (auto *wtable =
7380
IGF.tryGetLocalTypeData(packArchetypeType, localDataKind))
7481
return wtable;
@@ -656,17 +663,17 @@ llvm::Value *irgen::emitWitnessTablePackRef(IRGenFunction &IGF,
656663

657664
llvm::Value *irgen::emitTypeMetadataPackElementRef(
658665
IRGenFunction &IGF, CanPackType packType,
659-
ArrayRef<ProtocolDecl *> protocols, llvm::Value *index,
666+
ArrayRef<ProtocolConformanceRef> conformances, llvm::Value *index,
660667
DynamicMetadataRequest request,
661668
llvm::SmallVectorImpl<llvm::Value *> &wtables) {
662669
// If the packs have already been materialized, just gep into them.
663670
auto materializedMetadataPack =
664671
tryGetLocalPackTypeMetadata(IGF, packType, request);
665672
llvm::SmallVector<llvm::Value *> materializedWtablePacks;
666-
for (auto protocol : protocols) {
673+
for (auto conformance : conformances) {
667674
auto *wtablePack = tryGetLocalPackTypeData(
668675
IGF, packType,
669-
LocalTypeDataKind::forAbstractProtocolWitnessTable(protocol));
676+
LocalTypeDataKind::forProtocolWitnessTable(conformance));
670677
materializedWtablePacks.push_back(wtablePack);
671678
}
672679
if (materializedMetadataPack &&
@@ -696,10 +703,12 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
696703
auto ty = packType.getElementType(index);
697704
auto response = IGF.emitTypeMetadataRef(ty, request);
698705
auto *metadata = response.getMetadata();
699-
for (auto protocol : protocols) {
706+
for (auto conformance : conformances) {
707+
auto patternConformance = conformance.getPack()
708+
->getPatternConformances()[index];
700709
auto *wtable =
701710
emitWitnessTableRef(IGF, ty, /*srcMetadataCache=*/&metadata,
702-
ProtocolConformanceRef(protocol));
711+
patternConformance);
703712
wtables.push_back(wtable);
704713
}
705714
return metadata;
@@ -801,8 +810,8 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
801810
auto *metadataPhi = IGF.Builder.CreatePHI(IGF.IGM.TypeMetadataPtrTy,
802811
packType.getElementTypes().size());
803812
llvm::SmallVector<llvm::PHINode *, 2> wtablePhis;
804-
wtablePhis.reserve(protocols.size());
805-
for (auto idx : indices(protocols)) {
813+
wtablePhis.reserve(conformances.size());
814+
for (auto idx : indices(conformances)) {
806815
(void)idx;
807816
wtablePhis.push_back(IGF.Builder.CreatePHI(
808817
IGF.IGM.WitnessTablePtrTy, packType.getElementTypes().size()));
@@ -818,7 +827,9 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
818827
llvm::BasicBlock *previousInBounds = nullptr;
819828
// The lower bound of indices for the current pack expansion. Inclusive.
820829
llvm::Value *lowerBound = llvm::ConstantInt::get(IGF.IGM.SizeTy, 0);
821-
for (auto elementTy : packType.getElementTypes()) {
830+
for (unsigned i = 0, e = packType->getNumElements(); i < e; ++i) {
831+
auto elementTy = packType.getElementType(i);
832+
822833
// The block within which it will be checked whether %index corresponds to
823834
// an element of the pack expansion elementTy.
824835
auto *checkBounds = IGF.createBasicBlock("pack-index-element-bounds");
@@ -866,7 +877,7 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
866877

867878
llvm::Value *metadata = nullptr;
868879
llvm::SmallVector<llvm::Value *, 2> wtables;
869-
wtables.reserve(protocols.size());
880+
wtables.reserve(conformances.size());
870881
if (auto expansionTy = dyn_cast<PackExpansionType>(elementTy)) {
871882
// Actually materialize %inner. Then use it to get the metadata from the
872883
// pack expansion at that index.
@@ -876,19 +887,21 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
876887
auto patternTy = expansionTy.getPatternType();
877888
metadata = emitPackExpansionElementMetadata(IGF, context, patternTy,
878889
relativeIndex, request);
879-
for (auto protocol : protocols) {
890+
for (auto conformance : conformances) {
891+
auto patternConformance = conformance.getPack()->getPatternConformances()[i];
880892
auto *wtable = emitPackExpansionElementWitnessTable(
881-
IGF, context, patternTy, ProtocolConformanceRef(protocol),
893+
IGF, context, patternTy, patternConformance,
882894
&metadata, relativeIndex);
883895
wtables.push_back(wtable);
884896
}
885897
} else {
886898
metadata = IGF.emitTypeMetadataRef(elementTy, request).getMetadata();
887-
for (auto protocol : protocols) {
899+
for (auto conformance : conformances) {
900+
auto patternConformance = conformance.getPack()->getPatternConformances()[i];
888901
llvm::Value *_metadata = nullptr;
889902
auto *wtable =
890903
emitWitnessTableRef(IGF, elementTy, /*srcMetadataCache=*/&_metadata,
891-
ProtocolConformanceRef(protocol));
904+
patternConformance);
892905
wtables.push_back(wtable);
893906
}
894907
}
@@ -935,10 +948,12 @@ void irgen::bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
935948
openablePackParams.insert(genericParam->getCanonicalType());
936949
});
937950

951+
auto subs = environment->getPackElementContextSubstitutions();
952+
938953
// Find the archetypes and conformances which must be bound.
939954
llvm::SmallSetVector<CanType, 2> types;
940-
llvm::DenseMap<CanType, llvm::SmallVector<ProtocolDecl *, 2>>
941-
protocolsForType;
955+
llvm::DenseMap<CanType, llvm::SmallVector<ProtocolConformanceRef, 2>>
956+
conformancesForType;
942957
auto isDerivedFromPackElementGenericTypeParam = [&](CanType ty) -> bool {
943958
// Is this type itself an openable pack parameter OR a dependent type of
944959
// one?
@@ -954,16 +969,19 @@ void irgen::bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
954969
if (!isDerivedFromPackElementGenericTypeParam(ty))
955970
return;
956971
types.insert(ty);
957-
protocolsForType.insert({ty, {}});
972+
conformancesForType.insert({ty, {}});
958973
break;
959974
}
960975
case GenericRequirement::Kind::WitnessTablePack: {
961976
auto ty = requirement.getTypeParameter();
962977
if (!isDerivedFromPackElementGenericTypeParam(ty))
963978
return;
964979
types.insert(ty);
965-
auto iterator = protocolsForType.insert({ty, {}}).first;
966-
iterator->getSecond().push_back(requirement.getProtocol());
980+
auto iterator = conformancesForType.insert({ty, {}}).first;
981+
982+
auto conformance = subs.lookupConformance(
983+
ty, requirement.getProtocol());
984+
iterator->getSecond().push_back(conformance);
967985
break;
968986
}
969987
case GenericRequirement::Kind::Shape:
@@ -976,15 +994,14 @@ void irgen::bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
976994
// For each archetype to be bound, find the corresponding conformances and
977995
// bind the metadata and wtables.
978996
for (auto ty : types) {
979-
auto protocols = protocolsForType.find(ty)->getSecond();
997+
auto conformances = conformancesForType.find(ty)->getSecond();
980998
auto archetype = cast<ElementArchetypeType>(
981999
environment->mapPackTypeIntoElementContext(ty)->getCanonicalType());
982-
auto pack =
983-
cast<PackType>(environment->maybeApplyOuterContextSubstitutions(ty)
984-
->getCanonicalType());
1000+
auto packType = cast<PackType>(ty.subst(subs)->getCanonicalType());
1001+
9851002
llvm::SmallVector<llvm::Value *, 2> wtables;
9861003
auto *metadata = emitTypeMetadataPackElementRef(
987-
IGF, pack, protocols, index, MetadataState::Complete, wtables);
1004+
IGF, packType, conformances, index, MetadataState::Complete, wtables);
9881005
IGF.bindArchetype(archetype, metadata, MetadataState::Complete, wtables);
9891006
}
9901007
}

lib/IRGen/GenPack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
5959

6060
llvm::Value *
6161
emitTypeMetadataPackElementRef(IRGenFunction &IGF, CanPackType packType,
62-
ArrayRef<ProtocolDecl *> protocols,
62+
ArrayRef<ProtocolConformanceRef> conformances,
6363
llvm::Value *index,
6464
DynamicMetadataRequest request,
6565
llvm::SmallVectorImpl<llvm::Value *> &wtables);

0 commit comments

Comments
 (0)