Skip to content

Commit e2a41d1

Browse files
authored
Merge pull request #61737 from hborla/generic-environment-helpers
[GenericEnvironment] Add helper methods for mapping pack types to opened element types and vice versa.
2 parents ac131df + d09ea98 commit e2a41d1

File tree

8 files changed

+88
-66
lines changed

8 files changed

+88
-66
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,14 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
239239
/// Map a generic parameter type to a contextual type.
240240
Type mapTypeIntoContext(GenericTypeParamType *type) const;
241241

242+
/// Map a type containing parameter packs to a contextual type
243+
/// in the opened element generic context.
244+
Type mapPackTypeIntoElementContext(Type type) const;
245+
246+
/// Map a type containing pack element type parameters to a contextual
247+
/// type in the pack generic context.
248+
Type mapElementTypeIntoPackContext(Type type) const;
249+
242250
/// Map the given SIL interface type to a contextual type.
243251
///
244252
/// This operation will also reabstract dependent types according to the

include/swift/AST/Types.h

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

6164+
/// Returns a new GenericTypeParamType with the same depth and index
6165+
/// as this one, with the type parameter pack bit set.
6166+
GenericTypeParamType *asParameterPack(ASTContext &ctx) const;
6167+
6168+
/// Returns a new GenericTypeParamType with the same depth and index
6169+
/// as this one, removing the type parameter pack bit.
6170+
GenericTypeParamType *asScalar(ASTContext &ctx) const;
6171+
61646172
// Implement isa/cast/dyncast/etc.
61656173
static bool classof(const TypeBase *T) {
61666174
return T->getKind() == TypeKind::GenericTypeParam;

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5601,20 +5601,14 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
56015601
SmallVector<GenericTypeParamType *, 2> genericParams;
56025602
SmallVector<Requirement, 2> requirements;
56035603

5604-
auto eraseParameterPack = [&](GenericTypeParamType *paramType) {
5605-
return GenericTypeParamType::get(
5606-
/*isParameterPack=*/false, paramType->getDepth(),
5607-
paramType->getIndex(), *this);
5608-
};
5609-
56105604
for (auto paramType : baseGenericSig.getGenericParams()) {
5611-
genericParams.push_back(eraseParameterPack(paramType));
5605+
genericParams.push_back(paramType->asScalar(*this));
56125606
}
56135607

56145608
auto eraseParameterPackRec = [&](Type type) -> Type {
56155609
return type.transformRec([&](Type t) -> Optional<Type> {
56165610
if (auto *paramType = t->getAs<GenericTypeParamType>())
5617-
return Type(eraseParameterPack(paramType));
5611+
return Type(paramType->asScalar(*this));
56185612
return None;
56195613
});
56205614
};

lib/AST/GenericEnvironment.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,48 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
494494
return result;
495495
}
496496

497+
Type
498+
GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
499+
assert(getKind() == Kind::OpenedElement);
500+
assert(!type->hasArchetype());
501+
502+
auto sig = getGenericSignature();
503+
ASTContext &ctx = sig->getASTContext();
504+
QueryInterfaceTypeSubstitutions substitutions(this);
505+
506+
// Map the interface type to the element type by stripping
507+
// away the isParameterPack bit before mapping type parameters
508+
// to archetypes.
509+
return type.subst([&](SubstitutableType *type) {
510+
auto *genericParam = type->getAs<GenericTypeParamType>();
511+
if (!genericParam)
512+
return Type();
513+
514+
return substitutions(genericParam->asScalar(ctx));
515+
}, LookUpConformanceInSignature(sig.getPointer()));
516+
}
517+
518+
Type
519+
GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
520+
assert(getKind() == Kind::Primary);
521+
assert(!type->hasArchetype());
522+
523+
auto sig = getGenericSignature();
524+
ASTContext &ctx = sig->getASTContext();
525+
QueryInterfaceTypeSubstitutions substitutions(this);
526+
527+
// Map element archetypes to the pack archetypes by converting
528+
// element types to interface types and adding the isParameterPack
529+
// bit. Then, map type parameters to archetypes.
530+
return type.subst([&](SubstitutableType *type) {
531+
auto *genericParam = type->getAs<GenericTypeParamType>();
532+
if (!genericParam)
533+
return Type();
534+
535+
return substitutions(genericParam->asParameterPack(ctx));
536+
}, LookUpConformanceInSignature(sig.getPointer()));
537+
}
538+
497539
SubstitutionMap GenericEnvironment::getForwardingSubstitutionMap() const {
498540
auto genericSig = getGenericSignature();
499541
return SubstitutionMap::get(genericSig,

lib/AST/ParameterPack.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ bool GenericTypeParamType::isParameterPack() const {
5555
GenericTypeParamType::TYPE_SEQUENCE_BIT;
5656
}
5757

58+
GenericTypeParamType *
59+
GenericTypeParamType::asParameterPack(ASTContext &ctx) const {
60+
return GenericTypeParamType::get(/*isParameterPack*/true,
61+
getDepth(), getIndex(),
62+
ctx);
63+
}
64+
65+
GenericTypeParamType *
66+
GenericTypeParamType::asScalar(ASTContext &ctx) const {
67+
return GenericTypeParamType::get(/*isParameterPack*/false,
68+
getDepth(), getIndex(),
69+
ctx);
70+
}
71+
5872
/// G<{X1, ..., Xn}, {Y1, ..., Yn}>... => {G<X1, Y1>, ..., G<Xn, Yn>}...
5973
PackExpansionType *PackExpansionType::expand() {
6074
auto countType = getCountType();
@@ -278,4 +292,4 @@ unsigned ParameterList::getOrigParamIndex(SubstitutionMap subMap,
278292
subMap.dump(llvm::errs());
279293
dump(llvm::errs());
280294
abort();
281-
}
295+
}

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7089,37 +7089,15 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
70897089
auto toExpansionType = toType->getAs<PackExpansionType>();
70907090
auto *expansion = dyn_cast<PackExpansionExpr>(expr);
70917091

7092-
// FIXME: Duplicated code from `PackReferenceFinder` in PreCheckExpr.
7093-
auto toElementType = toExpansionType->getPatternType();
7094-
toElementType =
7095-
toElementType->mapTypeOutOfContext().transform([&](Type type) -> Type {
7096-
auto *genericParam = type->getAs<GenericTypeParamType>();
7097-
if (!genericParam || !genericParam->isParameterPack())
7098-
return type;
7099-
7100-
auto param = GenericTypeParamType::get(/*isParameterPack*/false,
7101-
genericParam->getDepth(),
7102-
genericParam->getIndex(), ctx);
7103-
return expansion->getGenericEnvironment()->mapTypeIntoContext(param);
7104-
});
7092+
auto *elementEnv = expansion->getGenericEnvironment();
7093+
auto toElementType = elementEnv->mapPackTypeIntoElementContext(
7094+
toExpansionType->getPatternType()->mapTypeOutOfContext());
71057095

71067096
auto *pattern = coerceToType(expansion->getPatternExpr(),
71077097
toElementType, locator);
7108-
7109-
// FIXME: Duplicated code from `visitPackExpansionExpr` in CSGen.
7110-
auto patternType =
7111-
cs.getType(pattern).transform([&](Type type) -> Type {
7112-
auto *element = type->getAs<ElementArchetypeType>();
7113-
if (!element)
7114-
return type;
7115-
7116-
auto *elementParam = element->mapTypeOutOfContext()->getAs<GenericTypeParamType>();
7117-
auto *pack = GenericTypeParamType::get(/*isParameterPack*/true,
7118-
elementParam->getDepth(),
7119-
elementParam->getIndex(),
7120-
ctx);
7121-
return cs.DC->mapTypeIntoContext(pack);
7122-
});
7098+
auto *packEnv = cs.DC->getGenericEnvironmentOfContext();
7099+
auto patternType = packEnv->mapElementTypeIntoPackContext(
7100+
toElementType->mapTypeOutOfContext());
71237101
auto shapeType = toExpansionType->getCountType();
71247102
auto expansionTy = PackExpansionType::get(patternType, shapeType);
71257103

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8464,20 +8464,11 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
84648464

84658465
// Replace opened element archetypes with pack archetypes
84668466
// for the resulting type of the pack expansion.
8467-
auto patternType = elementType.transform([&](Type type) -> Type {
8468-
auto *element = type->getAs<ElementArchetypeType>();
8469-
if (!element)
8470-
return type;
8471-
8472-
auto *elementParam = element->mapTypeOutOfContext()->getAs<GenericTypeParamType>();
8473-
auto *pack = GenericTypeParamType::get(/*isParameterPack*/true,
8474-
elementParam->getDepth(),
8475-
elementParam->getIndex(),
8476-
this->getASTContext());
8477-
return this->DC->mapTypeIntoContext(pack);
8478-
});
8479-
8467+
auto *environment = DC->getGenericEnvironmentOfContext();
8468+
auto patternType = environment->mapElementTypeIntoPackContext(
8469+
elementType->mapTypeOutOfContext());
84808470
addConstraint(ConstraintKind::Bind, second, patternType, locator);
8471+
84818472
return SolutionKind::Solved;
84828473
}
84838474

lib/Sema/PreCheckExpr.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -436,28 +436,15 @@ static Expr *getPackExpansion(DeclContext *dc, Expr *expr, SourceLoc opLoc) {
436436
if (auto expansionType = decl->getType()->getAs<PackExpansionType>()) {
437437
auto sourceRange = declRef->getSourceRange();
438438

439-
// Map the pattern interface type to the element interface type
440-
// by making all type parameter packs scalar type parameters.
441-
auto patternType = expansionType->getPatternType();
442-
auto elementInterfaceType =
443-
patternType->mapTypeOutOfContext().transform([&](Type type) -> Type {
444-
auto *genericParam = type->getAs<GenericTypeParamType>();
445-
if (!genericParam || !genericParam->isParameterPack())
446-
return type;
447-
448-
return GenericTypeParamType::get(/*isParameterPack*/false,
449-
genericParam->getDepth(),
450-
genericParam->getIndex(), ctx);
451-
});
452-
453-
// Map the element interface type into the context of the opened
439+
// Map the pattern interface type into the context of the opened
454440
// element signature.
455441
if (!environment) {
456442
auto sig = ctx.getOpenedElementSignature(
457443
dc->getGenericSignatureOfContext().getCanonicalSignature());
458444
environment = GenericEnvironment::forOpenedElement(sig, UUID::fromTime());
459445
}
460-
auto elementType = environment->mapTypeIntoContext(elementInterfaceType);
446+
auto elementType = environment->mapPackTypeIntoElementContext(
447+
expansionType->getPatternType()->mapTypeOutOfContext());
461448

462449
auto *opaqueValue = new (ctx) OpaqueValueExpr(sourceRange, elementType);
463450
opaqueValues.push_back(opaqueValue);

0 commit comments

Comments
 (0)