Skip to content

Commit 8ec5405

Browse files
committed
[GenericEnvironment] Store a substitution map for the outer generic parameters
of an opened pack element generic environment.
1 parent 6d65c11 commit 8ec5405

File tree

9 files changed

+94
-31
lines changed

9 files changed

+94
-31
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 15 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,6 +183,10 @@ 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

@@ -206,8 +212,11 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
206212
/// signature of the context whose element type is being opened, but with
207213
/// the pack parameter bit erased from one or more generic parameters
208214
/// \param uuid The unique identifier for this opened element
215+
/// \param outerSubs The substitution map containing archetypes from the
216+
/// outer generic context.
209217
static GenericEnvironment *
210-
forOpenedElement(GenericSignature signature, UUID uuid);
218+
forOpenedElement(GenericSignature signature, UUID uuid,
219+
SubstitutionMap outerSubs);
211220

212221
/// Make vanilla new/delete illegal.
213222
void *operator new(size_t Bytes) = delete;
@@ -219,8 +228,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
219228
return Mem;
220229
}
221230

222-
/// For an opaque archetype environment, apply the substitutions.
223-
Type maybeApplyOpaqueTypeSubstitutions(Type type) const;
231+
/// For an opaque or pack element archetype environment, apply the
232+
/// substitutions.
233+
Type maybeApplyOuterContextSubstitutions(Type type) const;
224234

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

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 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

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()->getAs<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
}

lib/AST/GenericEnvironment.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ SubstitutionMap GenericEnvironment::getOpaqueSubstitutions() const {
9797
return getTrailingObjects<OpaqueEnvironmentData>()->subMap;
9898
}
9999

100+
SubstitutionMap
101+
GenericEnvironment::getPackElementContextSubstitutions() const {
102+
assert(getKind() == Kind::OpenedElement);
103+
auto environmentData = getTrailingObjects<OpenedElementEnvironmentData>();
104+
return environmentData->outerSubstitutions;
105+
}
106+
100107
Type GenericEnvironment::getOpenedExistentialType() const {
101108
assert(getKind() == Kind::OpenedExistential);
102109
return getTrailingObjects<OpenedExistentialEnvironmentData>()->existential;
@@ -152,11 +159,11 @@ GenericEnvironment::GenericEnvironment(
152159
}
153160

154161
GenericEnvironment::GenericEnvironment(
155-
GenericSignature signature, UUID uuid)
162+
GenericSignature signature, UUID uuid, SubstitutionMap outerSubs)
156163
: SignatureAndKind(signature, Kind::OpenedElement)
157164
{
158165
new (getTrailingObjects<OpenedElementEnvironmentData>())
159-
OpenedElementEnvironmentData{uuid};
166+
OpenedElementEnvironmentData{uuid, outerSubs};
160167

161168
// Clear out the memory that holds the context types.
162169
std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(),
@@ -234,13 +241,21 @@ struct SubstituteOuterFromSubstitutionMap {
234241

235242
}
236243

237-
Type GenericEnvironment::maybeApplyOpaqueTypeSubstitutions(Type type) const {
244+
Type
245+
GenericEnvironment::maybeApplyOuterContextSubstitutions(Type type) const {
238246
switch (getKind()) {
239247
case Kind::Primary:
240248
case Kind::OpenedExistential:
241-
case Kind::OpenedElement:
242249
return type;
243250

251+
case Kind::OpenedElement: {
252+
auto packElements = getGenericSignature().getInnermostGenericParams();
253+
auto elementDepth = packElements.front()->getDepth();
254+
SubstituteOuterFromSubstitutionMap replacer{
255+
getPackElementContextSubstitutions(), elementDepth};
256+
return type.subst(replacer, replacer);
257+
}
258+
244259
case Kind::Opaque: {
245260
// Substitute outer generic parameters of an opaque archetype environment.
246261
unsigned opaqueDepth =
@@ -313,14 +328,14 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
313328
switch (getKind()) {
314329
case Kind::Primary:
315330
case Kind::OpenedExistential:
316-
case Kind::OpenedElement:
317331
if (type->hasTypeParameter()) {
318332
return mapTypeIntoContext(type, conformanceLookupFn);
319333
} else {
320334
return type;
321335
}
336+
case Kind::OpenedElement:
322337
case Kind::Opaque:
323-
return maybeApplyOpaqueTypeSubstitutions(type);
338+
return maybeApplyOuterContextSubstitutions(type);
324339
}
325340
};
326341

@@ -383,7 +398,7 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
383398
unsigned opaqueDepth =
384399
getOpaqueTypeDecl()->getOpaqueGenericParams().front()->getDepth();
385400
if (rootGP->getDepth() < opaqueDepth) {
386-
result = maybeApplyOpaqueTypeSubstitutions(requirements.anchor);
401+
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
387402
break;
388403
}
389404

@@ -419,10 +434,20 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
419434
break;
420435
}
421436

422-
case Kind::OpenedElement:
437+
case Kind::OpenedElement: {
438+
auto packElements = getGenericSignature().getInnermostGenericParams();
439+
auto elementDepth = packElements.front()->getDepth();
440+
441+
if (rootGP->getDepth() < elementDepth) {
442+
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
443+
break;
444+
}
445+
423446
result = ElementArchetypeType::getNew(this, requirements.anchor,
424447
requirements.protos, superclass,
425448
requirements.layout);
449+
break;
450+
}
426451
}
427452
}
428453

@@ -470,7 +495,7 @@ Type GenericEnvironment::mapTypeIntoContext(
470495
assert((!type->hasArchetype() || type->hasOpenedExistential()) &&
471496
"already have a contextual type");
472497

473-
type = maybeApplyOpaqueTypeSubstitutions(type);
498+
type = maybeApplyOuterContextSubstitutions(type);
474499
Type result = type.subst(QueryInterfaceTypeSubstitutions(this),
475500
lookupConformance,
476501
SubstFlags::AllowLoweredTypes);

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3627,7 +3627,7 @@ CanType OpaqueTypeArchetypeType::getCanonicalInterfaceType(Type interfaceType) {
36273627
auto sig = Environment->getOpaqueTypeDecl()
36283628
->getOpaqueInterfaceGenericSignature();
36293629
CanType canonicalType = interfaceType->getReducedType(sig);
3630-
return Environment->maybeApplyOpaqueTypeSubstitutions(canonicalType)
3630+
return Environment->maybeApplyOuterContextSubstitutions(canonicalType)
36313631
->getCanonicalType();
36323632
}
36333633

lib/Sema/PreCheckExpr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,11 @@ static Expr *getPackExpansion(DeclContext *dc, Expr *expr, SourceLoc opLoc) {
441441
if (!environment) {
442442
auto sig = ctx.getOpenedElementSignature(
443443
dc->getGenericSignatureOfContext().getCanonicalSignature());
444-
environment = GenericEnvironment::forOpenedElement(sig, UUID::fromTime());
444+
auto *contextEnv = dc->getGenericEnvironmentOfContext();
445+
auto contextSubs = contextEnv->getForwardingSubstitutionMap();
446+
environment =
447+
GenericEnvironment::forOpenedElement(sig, UUID::fromTime(),
448+
contextSubs);
445449
}
446450
auto elementType = environment->mapPackTypeIntoElementContext(
447451
expansionType->getPatternType()->mapTypeOutOfContext());

lib/Serialization/Deserialization.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,9 @@ ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID)
12241224
unsigned kind;
12251225
GenericSignatureID parentSigID;
12261226
TypeID existentialID;
1227-
GenericEnvironmentLayout::readRecord(scratch, kind, existentialID, parentSigID);
1227+
SubstitutionMapID subsID;
1228+
GenericEnvironmentLayout::readRecord(scratch, kind, existentialID,
1229+
parentSigID, subsID);
12281230

12291231
auto existentialTypeOrError = getTypeChecked(existentialID);
12301232
if (!existentialTypeOrError)
@@ -1234,6 +1236,10 @@ ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID)
12341236
if (!parentSigOrError)
12351237
return parentSigOrError.takeError();
12361238

1239+
auto contextSubsOrError = getSubstitutionMapChecked(subsID);
1240+
if (!contextSubsOrError)
1241+
return contextSubsOrError.takeError();
1242+
12371243
GenericEnvironment *genericEnv = nullptr;
12381244
switch (GenericEnvironmentKind(kind)) {
12391245
case GenericEnvironmentKind::OpenedExistential:
@@ -1243,7 +1249,7 @@ ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID)
12431249

12441250
case GenericEnvironmentKind::OpenedElement:
12451251
genericEnv = GenericEnvironment::forOpenedElement(
1246-
parentSigOrError.get(), UUID::fromTime());
1252+
parentSigOrError.get(), UUID::fromTime(), contextSubsOrError.get());
12471253
}
12481254

12491255
envOffset = genericEnv;

lib/Serialization/ModuleFormat.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 722; // has_symbol SIL serialization
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 723; // generic environment substitution
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1729,7 +1729,8 @@ namespace decls_block {
17291729
GENERIC_ENVIRONMENT,
17301730
BCFixed<1>, // GenericEnvironmentKind
17311731
TypeIDField, // existential type
1732-
GenericSignatureIDField // parent signature
1732+
GenericSignatureIDField, // parent signature
1733+
SubstitutionMapIDField // substitution map
17331734
>;
17341735

17351736
using SubstitutionMapLayout = BCRecordLayout<

lib/Serialization/Serialization.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,23 +1504,27 @@ void Serializer::writeASTBlockEntity(const GenericEnvironment *genericEnv) {
15041504
auto existentialTypeID = addTypeRef(genericEnv->getOpenedExistentialType());
15051505
auto parentSig = genericEnv->getOpenedExistentialParentSignature();
15061506
auto parentSigID = addGenericSignatureRef(parentSig);
1507+
auto emptySubs = SubstitutionMap();
1508+
auto subsID = addSubstitutionMapRef(emptySubs);
15071509

15081510
auto genericEnvAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
15091511
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, genericEnvAbbrCode,
15101512
unsigned(kind), existentialTypeID,
1511-
parentSigID);
1513+
parentSigID, subsID);
15121514
return;
15131515
}
15141516

15151517
case GenericEnvironment::Kind::OpenedElement: {
15161518
auto kind = GenericEnvironmentKind::OpenedElement;
15171519
auto parentSig = genericEnv->getGenericSignature();
15181520
auto parentSigID = addGenericSignatureRef(parentSig);
1521+
auto contextSubs = genericEnv->getPackElementContextSubstitutions();
1522+
auto subsID = addSubstitutionMapRef(contextSubs);
15191523

15201524
auto genericEnvAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
15211525
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, genericEnvAbbrCode,
15221526
unsigned(kind), /*existentialTypeID=*/0,
1523-
parentSigID);
1527+
parentSigID, subsID);
15241528
return;
15251529
}
15261530

0 commit comments

Comments
 (0)