Skip to content

Commit 2d893d2

Browse files
committed
[GenericEnvironment] For opened pack element environments, only include element type
parameters whose originating packs are in a given shape equivalence class.
1 parent 715de13 commit 2d893d2

File tree

11 files changed

+86
-28
lines changed

11 files changed

+86
-28
lines changed

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.

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5037,7 +5037,8 @@ GenericEnvironment::forOpenedExistential(
50375037

50385038
/// Create a new generic environment for an element archetype.
50395039
GenericEnvironment *
5040-
GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid,
5040+
GenericEnvironment::forOpenedElement(GenericSignature signature,
5041+
UUID uuid, CanType shapeClass,
50415042
SubstitutionMap outerSubs) {
50425043
auto &ctx = signature->getASTContext();
50435044

@@ -5060,7 +5061,8 @@ GenericEnvironment::forOpenedElement(GenericSignature signature, UUID uuid,
50605061
OpenedElementEnvironmentData, Type>(
50615062
0, 0, 1, numGenericParams);
50625063
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
5063-
auto *genericEnv = new (mem) GenericEnvironment(signature, uuid,
5064+
auto *genericEnv = new (mem) GenericEnvironment(signature,
5065+
uuid, shapeClass,
50645066
outerSubs);
50655067

50665068
openedElementEnvironments[uuid] = genericEnv;
@@ -5663,6 +5665,11 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig,
56635665
if (!paramType->isParameterPack())
56645666
continue;
56655667

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+
56665673
auto *elementParam = GenericTypeParamType::get(/*isParameterPack*/false,
56675674
packElementDepth,
56685675
packElementParams.size(),
@@ -5674,7 +5681,7 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig,
56745681
auto eraseParameterPackRec = [&](Type type) -> Type {
56755682
return type.transformRec([&](Type t) -> Optional<Type> {
56765683
if (auto *paramType = t->getAs<GenericTypeParamType>()) {
5677-
if (paramType->isParameterPack()) {
5684+
if (packElementParams.find(paramType) != packElementParams.end()) {
56785685
return Type(packElementParams[paramType]);
56795686
}
56805687

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ static void emitPackExpansionType(IRGenFunction &IGF,
177177
auto elementSig = IGF.IGM.Context.getOpenedElementSignature(
178178
genericSig, expansionTy.getCountType());
179179
auto *elementEnv = GenericEnvironment::forOpenedElement(
180-
elementSig, UUID::fromTime(), subMap);
180+
elementSig, UUID::fromTime(), expansionTy.getCountType(), subMap);
181181

182182
// Open each pack archetype.
183183
for (auto patternPackType : patternPacks) {

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7124,8 +7124,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
71247124
auto *pattern = coerceToType(expansion->getPatternExpr(),
71257125
toElementType, locator);
71267126
auto *packEnv = cs.DC->getGenericEnvironmentOfContext();
7127-
auto patternType = packEnv->mapElementTypeIntoPackContext(
7128-
toElementType->mapTypeOutOfContext());
7127+
auto patternType = packEnv->mapElementTypeIntoPackContext(toElementType);
71297128
auto shapeType = toExpansionType->getCountType();
71307129
auto expansionTy = PackExpansionType::get(patternType, shapeType);
71317130

lib/Sema/CSBindings.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,19 +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();
14271428
auto *elementEnv = CS.getPackElementEnvironment(constraint->getLocator(),
1428-
packType->getReducedShape());
1429+
shapeClass);
14291430
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
14301431
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
14311432

14321433
break;
14331434
} else if (packVar == TypeVar && !elementVar) {
14341435
// Produce a potential binding to the pack archetype corresponding to
14351436
// the opened element type.
1437+
Type patternType;
14361438
auto *packEnv = CS.DC->getGenericEnvironmentOfContext();
1437-
elementType = elementType->mapTypeOutOfContext();
1438-
auto patternType = packEnv->mapElementTypeIntoPackContext(elementType);
1439+
if (!elementType->hasElementArchetype()) {
1440+
patternType = elementType;
1441+
} else {
1442+
patternType = packEnv->mapElementTypeIntoPackContext(elementType);
1443+
}
1444+
14391445
addPotentialBinding({patternType, AllowedBindingKind::Exact, constraint});
14401446

14411447
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,8 @@ ConstraintSystem::getPackElementEnvironment(ConstraintLocator *locator,
655655
DC->getGenericSignatureOfContext().getCanonicalSignature(), shapeClass);
656656
auto *contextEnv = DC->getGenericEnvironmentOfContext();
657657
auto contextSubs = contextEnv->getForwardingSubstitutionMap();
658-
return GenericEnvironment::forOpenedElement(elementSig, uuid, contextSubs);
658+
return GenericEnvironment::forOpenedElement(elementSig, uuid, shapeClass,
659+
contextSubs);
659660
}
660661

661662
/// 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;

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,7 @@ namespace decls_block {
17591759
using GenericEnvironmentLayout = BCRecordLayout<
17601760
GENERIC_ENVIRONMENT,
17611761
BCFixed<1>, // GenericEnvironmentKind
1762-
TypeIDField, // existential type
1762+
TypeIDField, // existential type or shape class
17631763
GenericSignatureIDField, // parent signature
17641764
SubstitutionMapIDField // substitution map
17651765
>;

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1529,14 +1529,15 @@ void Serializer::writeASTBlockEntity(const GenericEnvironment *genericEnv) {
15291529

15301530
case GenericEnvironment::Kind::OpenedElement: {
15311531
auto kind = GenericEnvironmentKind::OpenedElement;
1532+
auto shapeClassID = addTypeRef(genericEnv->getOpenedElementShapeClass());
15321533
auto parentSig = genericEnv->getGenericSignature();
15331534
auto parentSigID = addGenericSignatureRef(parentSig);
15341535
auto contextSubs = genericEnv->getPackElementContextSubstitutions();
15351536
auto subsID = addSubstitutionMapRef(contextSubs);
15361537

15371538
auto genericEnvAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
15381539
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, genericEnvAbbrCode,
1539-
unsigned(kind), /*existentialTypeID=*/0,
1540+
unsigned(kind), shapeClassID,
15401541
parentSigID, subsID);
15411542
return;
15421543
}

0 commit comments

Comments
 (0)