Skip to content

Commit bfce692

Browse files
authored
Merge pull request #62904 from hborla/open-same-shape-packs
[GenericEnvironment] Only include opened pack elements within a given shape class in an opened element generic environment.
2 parents 08c5553 + 2d893d2 commit bfce692

File tree

13 files changed

+113
-42
lines changed

13 files changed

+113
-42
lines changed

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,8 @@ class ASTContext final {
13691369
///
13701370
/// This drops the parameter pack bit from each generic parameter,
13711371
/// and converts same-element requirements to same-type requirements.
1372-
CanGenericSignature getOpenedElementSignature(CanGenericSignature baseGenericSig);
1372+
CanGenericSignature getOpenedElementSignature(CanGenericSignature baseGenericSig,
1373+
CanType shapeClass);
13731374

13741375
GenericSignature getOverrideGenericSignature(const ValueDecl *base,
13751376
const ValueDecl *derived);

include/swift/AST/GenericEnvironment.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct OpenedExistentialEnvironmentData {
6767
/// Extra data in a generic environment for an opened pack element.
6868
struct OpenedElementEnvironmentData {
6969
UUID uuid;
70+
CanType shapeClass;
7071
SubstitutionMap outerSubstitutions;
7172
};
7273

@@ -140,7 +141,8 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
140141
Type existential, GenericSignature parentSig, UUID uuid);
141142

142143
/// Private constructor for opened element environments.
143-
explicit GenericEnvironment(GenericSignature signature, UUID uuid,
144+
explicit GenericEnvironment(GenericSignature signature,
145+
UUID uuid, CanType shapeClass,
144146
SubstitutionMap outerSubs);
145147

146148
friend ArchetypeType;
@@ -187,6 +189,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
187189
/// opened pack element generic environment.
188190
SubstitutionMap getPackElementContextSubstitutions() const;
189191

192+
/// Retrieve the shape equivalence class for an opened element environment.
193+
CanType getOpenedElementShapeClass() const;
194+
190195
/// Retrieve the UUID for an opened element environment.
191196
UUID getOpenedElementUUID() const;
192197

@@ -222,10 +227,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
222227
/// signature of the context whose element type is being opened, but with
223228
/// the pack parameter bit erased from one or more generic parameters
224229
/// \param uuid The unique identifier for this opened element
230+
/// \param shapeClass The shape equivalence class for the originating packs.
225231
/// \param outerSubs The substitution map containing archetypes from the
226232
/// outer generic context.
227233
static GenericEnvironment *
228-
forOpenedElement(GenericSignature signature, UUID uuid,
234+
forOpenedElement(GenericSignature signature,
235+
UUID uuid, CanType shapeClass,
229236
SubstitutionMap outerSubs);
230237

231238
/// Make vanilla new/delete illegal.

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3987,7 +3987,8 @@ class ConstraintSystem {
39873987
void addPackElementEnvironment(PackExpansionExpr *expr);
39883988

39893989
/// Get the opened element generic environment for the given locator.
3990-
GenericEnvironment *getPackElementEnvironment(ConstraintLocator *locator);
3990+
GenericEnvironment *getPackElementEnvironment(ConstraintLocator *locator,
3991+
CanType shapeClass);
39913992

39923993
/// Retrieve the constraint locator for the given anchor and
39933994
/// path, uniqued and automatically infer the summary flags

lib/AST/ASTContext.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,10 @@ struct ASTContext::Implementation {
356356
llvm::DenseMap<std::pair<CanType, const GenericSignatureImpl *>, CanGenericSignature>
357357
ExistentialSignatures;
358358

359-
/// The element signature for a generic signature, constructed by dropping
360-
/// the parameter pack bit from generic parameters.
361-
llvm::DenseMap<const GenericSignatureImpl *,
359+
/// The element signature for a generic signature, which contains a clone
360+
/// of the context generic signature with new type parameters and requirements
361+
/// for opened pack elements in the given shape equivalence class.
362+
llvm::DenseMap<std::pair<CanType, const GenericSignatureImpl *>,
362363
CanGenericSignature> ElementSignatures;
363364

364365
/// Overridden declarations.
@@ -5036,7 +5037,8 @@ GenericEnvironment::forOpenedExistential(
50365037

50375038
/// Create a new generic environment for an element archetype.
50385039
GenericEnvironment *
5039-
GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid,
5040+
GenericEnvironment::forOpenedElement(GenericSignature signature,
5041+
UUID uuid, CanType shapeClass,
50405042
SubstitutionMap outerSubs) {
50415043
auto &ctx = signature->getASTContext();
50425044

@@ -5059,7 +5061,8 @@ GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid,
50595061
OpenedElementEnvironmentData, Type>(
50605062
0, 0, 1, numGenericParams);
50615063
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
5062-
auto *genericEnv = new (mem) GenericEnvironment(signature, uuid,
5064+
auto *genericEnv = new (mem) GenericEnvironment(signature,
5065+
uuid, shapeClass,
50635066
outerSubs);
50645067

50655068
openedElementEnvironments[uuid] = genericEnv;
@@ -5624,9 +5627,11 @@ ASTContext::getOpenedExistentialSignature(Type type, GenericSignature parentSig)
56245627
}
56255628

56265629
CanGenericSignature
5627-
ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
5630+
ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig,
5631+
CanType shapeClass) {
56285632
auto &sigs = getImpl().ElementSignatures;
5629-
auto found = sigs.find(baseGenericSig.getPointer());
5633+
auto key = std::make_pair(shapeClass, baseGenericSig.getPointer());
5634+
auto found = sigs.find(key);
56305635
if (found != sigs.end())
56315636
return found->second;
56325637

@@ -5660,6 +5665,11 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
56605665
if (!paramType->isParameterPack())
56615666
continue;
56625667

5668+
// Only include opened element parameters for packs in the given
5669+
// shape equivalence class.
5670+
if (!baseGenericSig->haveSameShape(paramType, shapeClass->mapTypeOutOfContext()))
5671+
continue;
5672+
56635673
auto *elementParam = GenericTypeParamType::get(/*isParameterPack*/false,
56645674
packElementDepth,
56655675
packElementParams.size(),
@@ -5671,7 +5681,7 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
56715681
auto eraseParameterPackRec = [&](Type type) -> Type {
56725682
return type.transformRec([&](Type t) -> Optional<Type> {
56735683
if (auto *paramType = t->getAs<GenericTypeParamType>()) {
5674-
if (paramType->isParameterPack()) {
5684+
if (packElementParams.find(paramType) != packElementParams.end()) {
56755685
return Type(packElementParams[paramType]);
56765686
}
56775687

@@ -5718,7 +5728,7 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig) {
57185728
auto elementSig = buildGenericSignature(
57195729
*this, GenericSignature(), genericParams, requirements)
57205730
.getCanonicalSignature();
5721-
sigs[baseGenericSig.getPointer()] = elementSig;
5731+
sigs[key] = elementSig;
57225732
return elementSig;
57235733
}
57245734

lib/AST/GenericEnvironment.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ GenericEnvironment::getPackElementContextSubstitutions() const {
104104
return environmentData->outerSubstitutions;
105105
}
106106

107+
CanType GenericEnvironment::getOpenedElementShapeClass() const {
108+
assert(getKind() == Kind::OpenedElement);
109+
auto environmentData = getTrailingObjects<OpenedElementEnvironmentData>();
110+
return environmentData->shapeClass;
111+
}
112+
107113
Type GenericEnvironment::getOpenedExistentialType() const {
108114
assert(getKind() == Kind::OpenedExistential);
109115
return getTrailingObjects<OpenedExistentialEnvironmentData>()->existential;
@@ -127,7 +133,9 @@ UUID GenericEnvironment::getOpenedElementUUID() const {
127133

128134
void GenericEnvironment::getPackElementBindings(
129135
SmallVectorImpl<PackElementBinding> &bindings) const {
130-
auto packElements = getGenericSignature().getInnermostGenericParams();
136+
auto sig = getGenericSignature();
137+
auto shapeClass = getOpenedElementShapeClass();
138+
auto packElements = sig.getInnermostGenericParams();
131139
auto packElementDepth = packElements.front()->getDepth();
132140
auto elementIt = packElements.begin();
133141

@@ -141,6 +149,11 @@ void GenericEnvironment::getPackElementBindings(
141149
if (!genericParam->isParameterPack())
142150
continue;
143151

152+
// Only include opened element parameters for packs in the given
153+
// shape equivalence class.
154+
if (!sig->haveSameShape(genericParam, shapeClass->mapTypeOutOfContext()))
155+
continue;
156+
144157
assert(elementIt != packElements.end());
145158
auto *elementArchetype =
146159
mapTypeIntoContext(*elementIt++)->getAs<ElementArchetypeType>();
@@ -185,12 +198,13 @@ GenericEnvironment::GenericEnvironment(
185198
Type());
186199
}
187200

188-
GenericEnvironment::GenericEnvironment(
189-
GenericSignature signature, UUID uuid, SubstitutionMap outerSubs)
201+
GenericEnvironment::GenericEnvironment(GenericSignature signature,
202+
UUID uuid, CanType shapeClass,
203+
SubstitutionMap outerSubs)
190204
: SignatureAndKind(signature, Kind::OpenedElement)
191205
{
192206
new (getTrailingObjects<OpenedElementEnvironmentData>())
193-
OpenedElementEnvironmentData{uuid, outerSubs};
207+
OpenedElementEnvironmentData{uuid, shapeClass, outerSubs};
194208

195209
// Clear out the memory that holds the context types.
196210
std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(),
@@ -556,6 +570,7 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
556570
assert(!type->hasArchetype());
557571

558572
auto sig = getGenericSignature();
573+
auto shapeClass = getOpenedElementShapeClass();
559574
QueryInterfaceTypeSubstitutions substitutions(this);
560575

561576
llvm::SmallDenseMap<GenericParamKey,
@@ -570,6 +585,9 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
570585
if (!genericParam->isParameterPack())
571586
continue;
572587

588+
if (!sig->haveSameShape(genericParam, shapeClass->mapTypeOutOfContext()))
589+
continue;
590+
573591
auto elementIndex = elementParamForPack.size();
574592
elementParamForPack[{genericParam}] = packElements[elementIndex];
575593
}
@@ -592,11 +610,25 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
592610
Type
593611
GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
594612
assert(getKind() == Kind::Primary);
595-
assert(!type->hasArchetype());
613+
614+
// We need to pass in an archetype to get the shape class from its
615+
// generic environment.
616+
assert(type->hasElementArchetype());
617+
618+
ElementArchetypeType *element = nullptr;
619+
type.visit([&](Type type) {
620+
auto archetype = type->getAs<ElementArchetypeType>();
621+
if (!element && archetype)
622+
element = archetype;
623+
});
596624

597625
auto sig = getGenericSignature();
626+
auto *elementEnv = element->getGenericEnvironment();
627+
auto shapeClass = elementEnv->getOpenedElementShapeClass();
598628
QueryInterfaceTypeSubstitutions substitutions(this);
599629

630+
type = type->mapTypeOutOfContext();
631+
600632
llvm::SmallDenseMap<GenericParamKey, GenericTypeParamType *>
601633
packParamForElement;
602634
auto elementDepth =
@@ -606,6 +638,9 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
606638
if (!genericParam->isParameterPack())
607639
continue;
608640

641+
if (!sig->haveSameShape(genericParam, shapeClass->mapTypeOutOfContext()))
642+
continue;
643+
609644
GenericParamKey elementKey(/*isParameterPack*/false,
610645
/*depth*/elementDepth,
611646
/*index*/packParamForElement.size());

lib/IRGen/GenPack.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,10 @@ static void emitPackExpansionType(IRGenFunction &IGF,
174174
auto genericSig = genericEnv->getGenericSignature().getCanonicalSignature();
175175

176176
// Create an opened element signature and environment.
177-
auto elementSig = IGF.IGM.Context.getOpenedElementSignature(genericSig);
177+
auto elementSig = IGF.IGM.Context.getOpenedElementSignature(
178+
genericSig, expansionTy.getCountType());
178179
auto *elementEnv = GenericEnvironment::forOpenedElement(
179-
elementSig, UUID::fromTime(), subMap);
180+
elementSig, UUID::fromTime(), expansionTy.getCountType(), subMap);
180181

181182
// Open each pack archetype.
182183
for (auto patternPackType : patternPacks) {
@@ -325,4 +326,4 @@ void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF,
325326
IGF.Builder.CreateLifetimeEnd(pack.getAddress(),
326327
IGF.IGM.getPointerSize() * (*elementCount));
327328
}
328-
}
329+
}

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3818,11 +3818,16 @@ namespace {
38183818
}
38193819

38203820
Expr *visitPackExpansionExpr(PackExpansionExpr *expr) {
3821+
simplifyExprType(expr);
3822+
3823+
// Set the opened pack element environment for this pack expansion.
3824+
auto expansionTy = cs.getType(expr)->castTo<PackExpansionType>();
38213825
auto *locator = cs.getConstraintLocator(expr);
3822-
auto *environment = cs.getPackElementEnvironment(locator);
3826+
auto *environment = cs.getPackElementEnvironment(locator,
3827+
expansionTy->getCountType()->getCanonicalType());
38233828
expr->setGenericEnvironment(environment);
38243829

3825-
return simplifyExprType(expr);
3830+
return expr;
38263831
}
38273832

38283833
Expr *visitPackElementExpr(PackElementExpr *expr) {
@@ -7119,8 +7124,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
71197124
auto *pattern = coerceToType(expansion->getPatternExpr(),
71207125
toElementType, locator);
71217126
auto *packEnv = cs.DC->getGenericEnvironmentOfContext();
7122-
auto patternType = packEnv->mapElementTypeIntoPackContext(
7123-
toElementType->mapTypeOutOfContext());
7127+
auto patternType = packEnv->mapElementTypeIntoPackContext(toElementType);
71247128
auto shapeType = toExpansionType->getCountType();
71257129
auto expansionTy = PackExpansionType::get(patternType, shapeType);
71267130

lib/Sema/CSBindings.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,18 +1423,25 @@ void PotentialBindings::infer(Constraint *constraint) {
14231423
if (elementVar == TypeVar && !packVar) {
14241424
// Produce a potential binding to the opened element archetype corresponding
14251425
// to the pack type.
1426+
auto shapeClass = packType->getReducedShape();
14261427
packType = packType->mapTypeOutOfContext();
1427-
auto *elementEnv = CS.getPackElementEnvironment(constraint->getLocator());
1428+
auto *elementEnv = CS.getPackElementEnvironment(constraint->getLocator(),
1429+
shapeClass);
14281430
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
14291431
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
14301432

14311433
break;
14321434
} else if (packVar == TypeVar && !elementVar) {
14331435
// Produce a potential binding to the pack archetype corresponding to
14341436
// the opened element type.
1437+
Type patternType;
14351438
auto *packEnv = CS.DC->getGenericEnvironmentOfContext();
1436-
elementType = elementType->mapTypeOutOfContext();
1437-
auto patternType = packEnv->mapElementTypeIntoPackContext(elementType);
1439+
if (!elementType->hasElementArchetype()) {
1440+
patternType = elementType;
1441+
} else {
1442+
patternType = packEnv->mapElementTypeIntoPackContext(elementType);
1443+
}
1444+
14381445
addPotentialBinding({patternType, AllowedBindingKind::Exact, constraint});
14391446

14401447
break;

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8704,8 +8704,8 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
87048704

87058705
// This constraint only exists to vend bindings.
87068706
auto *packEnv = DC->getGenericEnvironmentOfContext();
8707-
if (packType->isEqual(packEnv->mapElementTypeIntoPackContext
8708-
(elementType->mapTypeOutOfContext()))) {
8707+
if ((!elementType->hasElementArchetype() && packType->isEqual(elementType)) ||
8708+
packType->isEqual(packEnv->mapElementTypeIntoPackContext(elementType))) {
87098709
return SolutionKind::Solved;
87108710
} else {
87118711
return SolutionKind::Error;

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,18 +643,20 @@ void ConstraintSystem::addPackElementEnvironment(PackExpansionExpr *expr) {
643643
}
644644

645645
GenericEnvironment *
646-
ConstraintSystem::getPackElementEnvironment(ConstraintLocator *locator) {
646+
ConstraintSystem::getPackElementEnvironment(ConstraintLocator *locator,
647+
CanType shapeClass) {
647648
auto result = PackExpansionEnvironments.find(locator);
648649
if (result == PackExpansionEnvironments.end())
649650
return nullptr;
650651

651652
auto uuid = result->second;
652653
auto &ctx = getASTContext();
653654
auto elementSig = ctx.getOpenedElementSignature(
654-
DC->getGenericSignatureOfContext().getCanonicalSignature());
655+
DC->getGenericSignatureOfContext().getCanonicalSignature(), shapeClass);
655656
auto *contextEnv = DC->getGenericEnvironmentOfContext();
656657
auto contextSubs = contextEnv->getForwardingSubstitutionMap();
657-
return GenericEnvironment::forOpenedElement(elementSig, uuid, contextSubs);
658+
return GenericEnvironment::forOpenedElement(elementSig, uuid, shapeClass,
659+
contextSubs);
658660
}
659661

660662
/// Extend the given depth map by adding depths for all of the subexpressions

lib/Serialization/Deserialization.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,14 +1261,14 @@ Expected<GenericEnvironment *> ModuleFile::getGenericEnvironmentChecked(
12611261

12621262
unsigned kind;
12631263
GenericSignatureID parentSigID;
1264-
TypeID existentialID;
1264+
TypeID existentialOrShapeID;
12651265
SubstitutionMapID subsID;
1266-
GenericEnvironmentLayout::readRecord(scratch, kind, existentialID,
1266+
GenericEnvironmentLayout::readRecord(scratch, kind, existentialOrShapeID,
12671267
parentSigID, subsID);
12681268

1269-
auto existentialTypeOrError = getTypeChecked(existentialID);
1270-
if (!existentialTypeOrError)
1271-
return existentialTypeOrError.takeError();
1269+
auto existentialOrShapeTypeOrError = getTypeChecked(existentialOrShapeID);
1270+
if (!existentialOrShapeTypeOrError)
1271+
return existentialOrShapeTypeOrError.takeError();
12721272

12731273
auto parentSigOrError = getGenericSignatureChecked(parentSigID);
12741274
if (!parentSigOrError)
@@ -1282,12 +1282,14 @@ Expected<GenericEnvironment *> ModuleFile::getGenericEnvironmentChecked(
12821282
switch (GenericEnvironmentKind(kind)) {
12831283
case GenericEnvironmentKind::OpenedExistential:
12841284
genericEnv = GenericEnvironment::forOpenedExistential(
1285-
existentialTypeOrError.get(), parentSigOrError.get(), UUID::fromTime());
1285+
existentialOrShapeTypeOrError.get(), parentSigOrError.get(), UUID::fromTime());
12861286
break;
12871287

12881288
case GenericEnvironmentKind::OpenedElement:
12891289
genericEnv = GenericEnvironment::forOpenedElement(
1290-
parentSigOrError.get(), UUID::fromTime(), contextSubsOrError.get());
1290+
parentSigOrError.get(), UUID::fromTime(),
1291+
existentialOrShapeTypeOrError.get()->getCanonicalType(),
1292+
contextSubsOrError.get());
12911293
}
12921294

12931295
envOffset = genericEnv;

0 commit comments

Comments
 (0)