Skip to content

Commit c225fc4

Browse files
authored
Merge pull request #62228 from hborla/pack-element-generic-environment
[GenericEnvironment] Include original parameter packs in opened pack element signatures.
2 parents 91cfd69 + d598c03 commit c225fc4

File tree

14 files changed

+301
-118
lines changed

14 files changed

+301
-118
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ struct OpenedExistentialEnvironmentData {
6464
UUID uuid;
6565
};
6666

67-
/// Extra data in a generic environment for an opened element.
67+
/// Extra data in a generic environment for an opened pack element.
6868
struct OpenedElementEnvironmentData {
6969
UUID uuid;
70+
SubstitutionMap outerSubstitutions;
7071
};
7172

7273
/// Describes the mapping between archetypes and interface types for the
@@ -139,7 +140,8 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
139140
Type existential, GenericSignature parentSig, UUID uuid);
140141

141142
/// Private constructor for opened element environments.
142-
explicit GenericEnvironment(GenericSignature signature, UUID uuid);
143+
explicit GenericEnvironment(GenericSignature signature, UUID uuid,
144+
SubstitutionMap outerSubs);
143145

144146
friend ArchetypeType;
145147
friend QueryInterfaceTypeSubstitutions;
@@ -181,9 +183,23 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
181183
/// create a generic environment.
182184
SubstitutionMap getOpaqueSubstitutions() const;
183185

186+
/// Retrieve the substitutions for the outer generic parameters of an
187+
/// opened pack element generic environment.
188+
SubstitutionMap getPackElementContextSubstitutions() const;
189+
184190
/// Retrieve the UUID for an opened element environment.
185191
UUID getOpenedElementUUID() const;
186192

193+
using PackElementBinding =
194+
std::pair<ElementArchetypeType *, PackArchetypeType *>;
195+
196+
/// Retrieve the bindings for the opened pack element archetypes in this
197+
/// generic environment to the pack archetypes that contain them.
198+
///
199+
/// \param bindings The vector to populate with the pack element bindings.
200+
void getPackElementBindings(
201+
SmallVectorImpl<PackElementBinding> &bindings) const;
202+
187203
/// Create a new, primary generic environment.
188204
static GenericEnvironment *forPrimary(GenericSignature signature);
189205

@@ -206,8 +222,11 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
206222
/// signature of the context whose element type is being opened, but with
207223
/// the pack parameter bit erased from one or more generic parameters
208224
/// \param uuid The unique identifier for this opened element
225+
/// \param outerSubs The substitution map containing archetypes from the
226+
/// outer generic context.
209227
static GenericEnvironment *
210-
forOpenedElement(GenericSignature signature, UUID uuid);
228+
forOpenedElement(GenericSignature signature, UUID uuid,
229+
SubstitutionMap outerSubs);
211230

212231
/// Make vanilla new/delete illegal.
213232
void *operator new(size_t Bytes) = delete;
@@ -219,8 +238,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
219238
return Mem;
220239
}
221240

222-
/// For an opaque archetype environment, apply the substitutions.
223-
Type maybeApplyOpaqueTypeSubstitutions(Type type) const;
241+
/// For an opaque or pack element archetype environment, apply the
242+
/// substitutions.
243+
Type maybeApplyOuterContextSubstitutions(Type type) const;
224244

225245
/// Compute the canonical interface type within this environment.
226246
Type getCanonicalInterfaceType(Type interfaceType);

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: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5016,7 +5016,8 @@ GenericEnvironment::forOpenedExistential(
50165016

50175017
/// Create a new generic environment for an element archetype.
50185018
GenericEnvironment *
5019-
GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid) {
5019+
GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid,
5020+
SubstitutionMap outerSubs) {
50205021
auto &ctx = signature->getASTContext();
50215022

50225023
auto &openedElementEnvironments =
@@ -5038,7 +5039,8 @@ GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid) {
50385039
OpenedElementEnvironmentData, Type>(
50395040
0, 0, 1, numGenericParams);
50405041
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
5041-
auto *genericEnv = new (mem) GenericEnvironment(signature, uuid);
5042+
auto *genericEnv = new (mem) GenericEnvironment(signature, uuid,
5043+
outerSubs);
50425044

50435045
openedElementEnvironments[uuid] = genericEnv;
50445046

@@ -5621,41 +5623,76 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
56215623
}
56225624
#endif
56235625

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

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

56315651
auto eraseParameterPackRec = [&](Type type) -> Type {
56325652
return type.transformRec([&](Type t) -> Optional<Type> {
5633-
if (auto *paramType = t->getAs<GenericTypeParamType>())
5634-
return Type(paramType->asScalar(*this));
5653+
if (auto *paramType = t->getAs<GenericTypeParamType>()) {
5654+
if (paramType->isParameterPack()) {
5655+
return Type(packElementParams[paramType]);
5656+
}
5657+
5658+
return t;
5659+
}
56355660
return None;
56365661
});
56375662
};
56385663

56395664
for (auto requirement : baseGenericSig.getRequirements()) {
5665+
requirements.push_back(requirement);
5666+
5667+
// If this requirement contains parameter packs, create a new requirement
5668+
// for the corresponding pack element.
56405669
switch (requirement.getKind()) {
56415670
case RequirementKind::SameShape:
56425671
// Drop same-shape requirements from the element signature.
56435672
break;
56445673
case RequirementKind::Conformance:
56455674
case RequirementKind::Superclass:
5646-
case RequirementKind::SameType:
5647-
requirements.emplace_back(
5648-
requirement.getKind(),
5649-
eraseParameterPackRec(requirement.getFirstType()),
5650-
eraseParameterPackRec(requirement.getSecondType()));
5675+
case RequirementKind::SameType: {
5676+
auto firstType = eraseParameterPackRec(requirement.getFirstType());
5677+
auto secondType = eraseParameterPackRec(requirement.getSecondType());
5678+
if (firstType->isEqual(requirement.getFirstType()) &&
5679+
secondType->isEqual(requirement.getSecondType()))
5680+
break;
5681+
5682+
requirements.emplace_back(requirement.getKind(),
5683+
firstType, secondType);
56515684
break;
5652-
case RequirementKind::Layout:
5653-
requirements.emplace_back(
5654-
requirement.getKind(),
5655-
eraseParameterPackRec(requirement.getFirstType()),
5656-
requirement.getLayoutConstraint());
5685+
}
5686+
case RequirementKind::Layout: {
5687+
auto firstType = eraseParameterPackRec(requirement.getFirstType());
5688+
if (firstType->isEqual(requirement.getFirstType()))
5689+
break;
5690+
5691+
requirements.emplace_back(requirement.getKind(), firstType,
5692+
requirement.getLayoutConstraint());
56575693
break;
56585694
}
5695+
}
56595696
}
56605697

56615698
auto elementSig = buildGenericSignature(

lib/AST/ASTVerifier.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class Verifier : public ASTWalker {
196196
SmallVector<ScopeLike, 4> Scopes;
197197

198198
/// The stack of generic contexts.
199-
using GenericLike = llvm::PointerUnion<DeclContext *, GenericSignature>;
199+
using GenericLike = llvm::PointerUnion<DeclContext *, GenericEnvironment *>;
200200
SmallVector<GenericLike, 2> Generics;
201201

202202
/// The stack of optional evaluations active at this point.
@@ -634,10 +634,21 @@ class Verifier : public ASTWalker {
634634

635635
auto genericCtx = Generics.back();
636636
GenericSignature genericSig;
637-
if (auto *genericDC = genericCtx.dyn_cast<DeclContext *>())
637+
if (auto *genericDC = genericCtx.dyn_cast<DeclContext *>()) {
638638
genericSig = genericDC->getGenericSignatureOfContext();
639-
else
640-
genericSig = genericCtx.get<GenericSignature>();
639+
} else {
640+
auto *genericEnv = genericCtx.get<GenericEnvironment *>();
641+
genericSig = genericEnv->getGenericSignature();
642+
643+
// Check whether this archetype is a substitution from the
644+
// outer generic context of an opened element environment.
645+
if (genericEnv->getKind() == GenericEnvironment::Kind::OpenedElement) {
646+
auto contextSubs = genericEnv->getPackElementContextSubstitutions();
647+
QuerySubstitutionMap isInContext{contextSubs};
648+
if (isInContext(root->getInterfaceType()->castTo<GenericTypeParamType>()))
649+
return false;
650+
}
651+
}
641652

642653
if (genericSig.getPointer() != archetypeSig.getPointer()) {
643654
Out << "Archetype " << root->getString() << " not allowed "
@@ -824,7 +835,7 @@ class Verifier : public ASTWalker {
824835
if (!shouldVerify(cast<Expr>(expr)))
825836
return false;
826837

827-
Generics.push_back(expr->getGenericEnvironment()->getGenericSignature());
838+
Generics.push_back(expr->getGenericEnvironment());
828839

829840
for (auto *placeholder : expr->getOpaqueValues()) {
830841
assert(!OpaqueValues.count(placeholder));
@@ -837,8 +848,8 @@ class Verifier : public ASTWalker {
837848
void verifyCheckedAlways(PackExpansionExpr *E) {
838849
// Remove the element generic environment before verifying
839850
// the pack expansion type, which contains pack archetypes.
840-
assert(Generics.back().get<GenericSignature>().getPointer() ==
841-
E->getGenericEnvironment()->getGenericSignature().getPointer());
851+
assert(Generics.back().get<GenericEnvironment *>() ==
852+
E->getGenericEnvironment());
842853
Generics.pop_back();
843854
verifyCheckedAlwaysBase(E);
844855
}

0 commit comments

Comments
 (0)