Skip to content

Commit 6d65c11

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 1f3e159 commit 6d65c11

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
@@ -6188,14 +6188,6 @@ class GenericTypeParamType : public SubstitutableType {
61886188
/// \endcode
61896189
bool isParameterPack() const;
61906190

6191-
/// Returns a new GenericTypeParamType with the same depth and index
6192-
/// as this one, with the type parameter pack bit set.
6193-
GenericTypeParamType *asParameterPack(ASTContext &ctx) const;
6194-
6195-
/// Returns a new GenericTypeParamType with the same depth and index
6196-
/// as this one, removing the type parameter pack bit.
6197-
GenericTypeParamType *asScalar(ASTContext &ctx) const;
6198-
61996191
// Implement isa/cast/dyncast/etc.
62006192
static bool classof(const TypeBase *T) {
62016193
return T->getKind() == TypeKind::GenericTypeParam;

lib/AST/ASTContext.cpp

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5621,41 +5621,76 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
56215621
}
56225622
#endif
56235623

5624-
SmallVector<GenericTypeParamType *, 2> genericParams;
5624+
// The pack element signature includes all type parameters and requirements
5625+
// from the outer context, plus a new set of type parameters representing
5626+
// open pack elements and their corresponding element requirements.
5627+
5628+
llvm::SmallMapVector<GenericTypeParamType *,
5629+
GenericTypeParamType *, 2> packElementParams;
5630+
SmallVector<GenericTypeParamType *, 2> genericParams(
5631+
baseGenericSig.getGenericParams().begin(), baseGenericSig.getGenericParams().end());
56255632
SmallVector<Requirement, 2> requirements;
56265633

5634+
auto packElementDepth =
5635+
baseGenericSig.getInnermostGenericParams().front()->getDepth() + 1;
5636+
56275637
for (auto paramType : baseGenericSig.getGenericParams()) {
5628-
genericParams.push_back(paramType->asScalar(*this));
5638+
if (!paramType->isParameterPack())
5639+
continue;
5640+
5641+
auto *elementParam = GenericTypeParamType::get(/*isParameterPack*/false,
5642+
packElementDepth,
5643+
packElementParams.size(),
5644+
*this);
5645+
genericParams.push_back(elementParam);
5646+
packElementParams[paramType] = elementParam;
56295647
}
56305648

56315649
auto eraseParameterPackRec = [&](Type type) -> Type {
56325650
return type.transformRec([&](Type t) -> Optional<Type> {
5633-
if (auto *paramType = t->getAs<GenericTypeParamType>())
5634-
return Type(paramType->asScalar(*this));
5651+
if (auto *paramType = t->getAs<GenericTypeParamType>()) {
5652+
if (paramType->isParameterPack()) {
5653+
return Type(packElementParams[paramType]);
5654+
}
5655+
5656+
return t;
5657+
}
56355658
return None;
56365659
});
56375660
};
56385661

56395662
for (auto requirement : baseGenericSig.getRequirements()) {
5663+
requirements.push_back(requirement);
5664+
5665+
// If this requirement contains parameter packs, create a new requirement
5666+
// for the corresponding pack element.
56405667
switch (requirement.getKind()) {
56415668
case RequirementKind::SameShape:
56425669
// Drop same-shape requirements from the element signature.
56435670
break;
56445671
case RequirementKind::Conformance:
56455672
case RequirementKind::Superclass:
5646-
case RequirementKind::SameType:
5647-
requirements.emplace_back(
5648-
requirement.getKind(),
5649-
eraseParameterPackRec(requirement.getFirstType()),
5650-
eraseParameterPackRec(requirement.getSecondType()));
5673+
case RequirementKind::SameType: {
5674+
auto firstType = eraseParameterPackRec(requirement.getFirstType());
5675+
auto secondType = eraseParameterPackRec(requirement.getSecondType());
5676+
if (firstType->isEqual(requirement.getFirstType()) &&
5677+
secondType->isEqual(requirement.getSecondType()))
5678+
break;
5679+
5680+
requirements.emplace_back(requirement.getKind(),
5681+
firstType, secondType);
56515682
break;
5652-
case RequirementKind::Layout:
5653-
requirements.emplace_back(
5654-
requirement.getKind(),
5655-
eraseParameterPackRec(requirement.getFirstType()),
5656-
requirement.getLayoutConstraint());
5683+
}
5684+
case RequirementKind::Layout: {
5685+
auto firstType = eraseParameterPackRec(requirement.getFirstType());
5686+
if (firstType->isEqual(requirement.getFirstType()))
5687+
break;
5688+
5689+
requirements.emplace_back(requirement.getKind(), firstType,
5690+
requirement.getLayoutConstraint());
56575691
break;
56585692
}
5693+
}
56595694
}
56605695

56615696
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)