Skip to content

Commit da6d51c

Browse files
committed
Always use PackTypes as the substitutions for type parameter packs
1 parent d103bf7 commit da6d51c

File tree

7 files changed

+60
-7
lines changed

7 files changed

+60
-7
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6699,6 +6699,10 @@ class PackType final : public TypeBase, public llvm::FoldingSetNode,
66996699
TypeArrayView<GenericTypeParamType> params,
67006700
ArrayRef<Type> args);
67016701

6702+
/// Given a pack parameter or pack archetype `T`, produce the
6703+
/// pack type `Pack{repeat each T}`.
6704+
static PackType *getSingletonPackExpansion(Type packParam);
6705+
67026706
public:
67036707
/// Retrieves the number of elements in this pack.
67046708
unsigned getNumElements() const { return Bits.PackType.Count; }

lib/AST/ASTContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,6 +3302,13 @@ PackType *PackType::getEmpty(const ASTContext &C) {
33023302
return cast<PackType>(CanType(C.TheEmptyPackType));
33033303
}
33043304

3305+
PackType *PackType::getSingletonPackExpansion(Type param) {
3306+
assert((param->is<GenericTypeParamType>() &&
3307+
param->castTo<GenericTypeParamType>()->isParameterPack()) ||
3308+
(param->is<PackArchetypeType>()));
3309+
return get(param->getASTContext(), {PackExpansionType::get(param, param)});
3310+
}
3311+
33053312
CanPackType CanPackType::get(const ASTContext &C, ArrayRef<CanType> elements) {
33063313
SmallVector<Type, 8> ncElements(elements.begin(), elements.end());
33073314
return CanPackType(PackType::get(C, ncElements));

lib/AST/Decl.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4623,8 +4623,12 @@ static Type computeNominalType(NominalTypeDecl *decl, DeclTypeKind kind) {
46234623
// the generic parameter list directly instead of looking
46244624
// at the signature.
46254625
SmallVector<Type, 4> args;
4626-
for (auto param : decl->getGenericParams()->getParams())
4627-
args.push_back(param->getDeclaredInterfaceType());
4626+
for (auto param : decl->getGenericParams()->getParams()) {
4627+
auto argTy = param->getDeclaredInterfaceType();
4628+
if (param->isParameterPack())
4629+
argTy = PackType::getSingletonPackExpansion(argTy);
4630+
args.push_back(argTy);
4631+
}
46284632

46294633
return BoundGenericType::get(decl, ParentTy, args);
46304634
}

lib/AST/GenericEnvironment.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,37 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
681681
}, LookUpConformanceInSignature(sig.getPointer()));
682682
}
683683

684+
namespace {
685+
/// A function suitable for use as a \c TypeSubstitutionFn that produces
686+
/// correct forwarding substitutions for a generic environment.
687+
///
688+
/// This differs from QueryInterfaceTypeSubstitutions only in that it
689+
/// always produces PackTypes for pack parameters.
690+
class BuildForwardingSubstitutions {
691+
QueryInterfaceTypeSubstitutions Query;
692+
693+
public:
694+
BuildForwardingSubstitutions(const GenericEnvironment *self)
695+
: Query(self) { }
696+
697+
Type operator()(SubstitutableType *type) const;
698+
};
699+
} // end anonymous namespace
700+
701+
Type BuildForwardingSubstitutions::operator()(SubstitutableType *type) const {
702+
if (auto resultType = Query(type)) {
703+
auto param = type->castTo<GenericTypeParamType>();
704+
if (!param->isParameterPack())
705+
return resultType;
706+
return PackType::getSingletonPackExpansion(resultType);
707+
}
708+
return Type();
709+
}
710+
684711
SubstitutionMap GenericEnvironment::getForwardingSubstitutionMap() const {
685712
auto genericSig = getGenericSignature();
686713
return SubstitutionMap::get(genericSig,
687-
QueryInterfaceTypeSubstitutions(this),
714+
BuildForwardingSubstitutions(this),
688715
MakeAbstractConformanceForGenericType());
689716
}
690717

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -566,10 +566,13 @@ unsigned GenericParamKey::findIndexIn(
566566

567567
SubstitutionMap GenericSignatureImpl::getIdentitySubstitutionMap() const {
568568
return SubstitutionMap::get(const_cast<GenericSignatureImpl *>(this),
569-
[](SubstitutableType *t) -> Type {
570-
return Type(cast<GenericTypeParamType>(t));
571-
},
572-
MakeAbstractConformanceForGenericType());
569+
[](SubstitutableType *t) -> Type {
570+
auto param = cast<GenericTypeParamType>(t);
571+
if (!param->isParameterPack())
572+
return param;
573+
return PackType::getSingletonPackExpansion(param);
574+
},
575+
MakeAbstractConformanceForGenericType());
573576
}
574577

575578
GenericTypeParamType *GenericSignatureImpl::getSugaredType(

lib/AST/SubstitutionMap.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
226226

227227
// Record the replacement.
228228
Type replacement = Type(gp).subst(subs, lookupConformance);
229+
230+
assert((!replacement || replacement->hasError() ||
231+
gp->isParameterPack() == replacement->is<PackType>()) &&
232+
"replacement for pack parameter must be a pack type");
233+
229234
replacementTypes.push_back(replacement);
230235
});
231236

lib/AST/Type.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4954,6 +4954,9 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
49544954
else if (genericEnv)
49554955
substTy = genericEnv->mapTypeIntoContext(gp);
49564956

4957+
if (gp->isParameterPack() && !substTy->hasError())
4958+
substTy = PackType::getSingletonPackExpansion(substTy);
4959+
49574960
auto result = substitutions.insert(
49584961
{gp->getCanonicalType()->castTo<GenericTypeParamType>(),
49594962
substTy});

0 commit comments

Comments
 (0)