Skip to content

Commit aaee172

Browse files
committed
[GenericEnvironment] Model opened pack element signatures as a complete clone
of the outer context signature, with an additional set of element type parameters at depth + 1.
1 parent f63de71 commit aaee172

File tree

4 files changed

+88
-40
lines changed

4 files changed

+88
-40
lines changed

include/swift/AST/Types.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6177,14 +6177,6 @@ class GenericTypeParamType : public SubstitutableType {
61776177
/// \endcode
61786178
bool isParameterPack() const;
61796179

6180-
/// Returns a new GenericTypeParamType with the same depth and index
6181-
/// as this one, with the type parameter pack bit set.
6182-
GenericTypeParamType *asParameterPack(ASTContext &ctx) const;
6183-
6184-
/// Returns a new GenericTypeParamType with the same depth and index
6185-
/// as this one, removing the type parameter pack bit.
6186-
GenericTypeParamType *asScalar(ASTContext &ctx) const;
6187-
61886180
// Implement isa/cast/dyncast/etc.
61896181
static bool classof(const TypeBase *T) {
61906182
return T->getKind() == TypeKind::GenericTypeParam;

lib/AST/ASTContext.cpp

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5629,41 +5629,76 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
56295629
}
56305630
#endif
56315631

5632-
SmallVector<GenericTypeParamType *, 2> genericParams;
5632+
// The pack element signature includes all type parameters and requirements
5633+
// from the outer context, plus a new set of type parameters representing
5634+
// open pack elements and their corresponding element requirements.
5635+
5636+
llvm::SmallMapVector<GenericTypeParamType *,
5637+
GenericTypeParamType *, 2> packElementParams;
5638+
SmallVector<GenericTypeParamType *, 2> genericParams(
5639+
baseGenericSig.getGenericParams().begin(), baseGenericSig.getGenericParams().end());
56335640
SmallVector<Requirement, 2> requirements;
56345641

5642+
auto packElementDepth =
5643+
baseGenericSig.getInnermostGenericParams().front()->getDepth() + 1;
5644+
56355645
for (auto paramType : baseGenericSig.getGenericParams()) {
5636-
genericParams.push_back(paramType->asScalar(*this));
5646+
if (!paramType->isParameterPack())
5647+
continue;
5648+
5649+
auto *elementParam = GenericTypeParamType::get(/*isParameterPack*/false,
5650+
packElementDepth,
5651+
packElementParams.size(),
5652+
*this);
5653+
genericParams.push_back(elementParam);
5654+
packElementParams[paramType] = elementParam;
56375655
}
56385656

56395657
auto eraseParameterPackRec = [&](Type type) -> Type {
56405658
return type.transformRec([&](Type t) -> Optional<Type> {
5641-
if (auto *paramType = t->getAs<GenericTypeParamType>())
5642-
return Type(paramType->asScalar(*this));
5659+
if (auto *paramType = t->getAs<GenericTypeParamType>()) {
5660+
if (paramType->isParameterPack()) {
5661+
return Type(packElementParams[paramType]);
5662+
}
5663+
5664+
return t;
5665+
}
56435666
return None;
56445667
});
56455668
};
56465669

56475670
for (auto requirement : baseGenericSig.getRequirements()) {
5671+
requirements.push_back(requirement);
5672+
5673+
// If this requirement contains parameter packs, create a new requirement
5674+
// for the corresponding pack element.
56485675
switch (requirement.getKind()) {
56495676
case RequirementKind::SameShape:
56505677
// Drop same-shape requirements from the element signature.
56515678
break;
56525679
case RequirementKind::Conformance:
56535680
case RequirementKind::Superclass:
5654-
case RequirementKind::SameType:
5655-
requirements.emplace_back(
5656-
requirement.getKind(),
5657-
eraseParameterPackRec(requirement.getFirstType()),
5658-
eraseParameterPackRec(requirement.getSecondType()));
5681+
case RequirementKind::SameType: {
5682+
auto firstType = eraseParameterPackRec(requirement.getFirstType());
5683+
auto secondType = eraseParameterPackRec(requirement.getSecondType());
5684+
if (firstType->isEqual(requirement.getFirstType()) &&
5685+
secondType->isEqual(requirement.getSecondType()))
5686+
break;
5687+
5688+
requirements.emplace_back(requirement.getKind(),
5689+
firstType, secondType);
56595690
break;
5660-
case RequirementKind::Layout:
5661-
requirements.emplace_back(
5662-
requirement.getKind(),
5663-
eraseParameterPackRec(requirement.getFirstType()),
5664-
requirement.getLayoutConstraint());
5691+
}
5692+
case RequirementKind::Layout: {
5693+
auto firstType = eraseParameterPackRec(requirement.getFirstType());
5694+
if (firstType->isEqual(requirement.getFirstType()))
5695+
break;
5696+
5697+
requirements.emplace_back(requirement.getKind(), firstType,
5698+
requirement.getLayoutConstraint());
56655699
break;
56665700
}
5701+
}
56675702
}
56685703

56695704
auto elementSig = buildGenericSignature(

lib/AST/GenericEnvironment.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,24 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
500500
assert(!type->hasArchetype());
501501

502502
auto sig = getGenericSignature();
503-
ASTContext &ctx = sig->getASTContext();
504503
QueryInterfaceTypeSubstitutions substitutions(this);
505504

505+
llvm::SmallDenseMap<GenericParamKey,
506+
GenericTypeParamType *> elementParamForPack;
507+
auto packElements = sig.getInnermostGenericParams();
508+
auto elementDepth = packElements.front()->getDepth();
509+
510+
for (auto *genericParam : sig.getGenericParams()) {
511+
if (genericParam->getDepth() == elementDepth)
512+
break;
513+
514+
if (!genericParam->isParameterPack())
515+
continue;
516+
517+
auto elementIndex = elementParamForPack.size();
518+
elementParamForPack[{genericParam}] = packElements[elementIndex];
519+
}
520+
506521
// Map the interface type to the element type by stripping
507522
// away the isParameterPack bit before mapping type parameters
508523
// to archetypes.
@@ -511,7 +526,10 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
511526
if (!genericParam)
512527
return Type();
513528

514-
return substitutions(genericParam->asScalar(ctx));
529+
if (auto *elementParam = elementParamForPack[{genericParam}])
530+
return substitutions(elementParam);
531+
532+
return substitutions(genericParam);
515533
}, LookUpConformanceInSignature(sig.getPointer()));
516534
}
517535

@@ -521,9 +539,23 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
521539
assert(!type->hasArchetype());
522540

523541
auto sig = getGenericSignature();
524-
ASTContext &ctx = sig->getASTContext();
525542
QueryInterfaceTypeSubstitutions substitutions(this);
526543

544+
llvm::SmallDenseMap<GenericParamKey, GenericTypeParamType *>
545+
packParamForElement;
546+
auto elementDepth =
547+
sig.getInnermostGenericParams().front()->getDepth() + 1;
548+
549+
for (auto *genericParam : sig.getGenericParams()) {
550+
if (!genericParam->isParameterPack())
551+
continue;
552+
553+
GenericParamKey elementKey(/*isParameterPack*/false,
554+
/*depth*/elementDepth,
555+
/*index*/packParamForElement.size());
556+
packParamForElement[elementKey] = genericParam;
557+
}
558+
527559
// Map element archetypes to the pack archetypes by converting
528560
// element types to interface types and adding the isParameterPack
529561
// bit. Then, map type parameters to archetypes.
@@ -532,7 +564,10 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
532564
if (!genericParam)
533565
return Type();
534566

535-
return substitutions(genericParam->asParameterPack(ctx));
567+
if (auto *packParam = packParamForElement[{genericParam}])
568+
return substitutions(packParam);
569+
570+
return substitutions(genericParam);
536571
}, LookUpConformanceInSignature(sig.getPointer()));
537572
}
538573

lib/AST/ParameterPack.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,6 @@ bool GenericTypeParamType::isParameterPack() const {
6767
GenericTypeParamType::TYPE_SEQUENCE_BIT;
6868
}
6969

70-
GenericTypeParamType *
71-
GenericTypeParamType::asParameterPack(ASTContext &ctx) const {
72-
return GenericTypeParamType::get(/*isParameterPack*/true,
73-
getDepth(), getIndex(),
74-
ctx);
75-
}
76-
77-
GenericTypeParamType *
78-
GenericTypeParamType::asScalar(ASTContext &ctx) const {
79-
return GenericTypeParamType::get(/*isParameterPack*/false,
80-
getDepth(), getIndex(),
81-
ctx);
82-
}
83-
8470
/// G<{X1, ..., Xn}, {Y1, ..., Yn}>... => {G<X1, Y1>, ..., G<Xn, Yn>}...
8571
PackExpansionType *PackExpansionType::expand() {
8672
auto countType = getCountType();

0 commit comments

Comments
 (0)