Skip to content

Commit cfb4e60

Browse files
authored
Merge pull request #60523 from slavapestov/fix-opened-generic-environment-identity
Serialization: Preserve identity of opened generic environments
2 parents 8bf745b + 9c094c5 commit cfb4e60

16 files changed

+221
-121
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class QueryInterfaceTypeSubstitutions {
5454
/// Extra data in a generic environment for an opened existential.
5555
struct OpenedGenericEnvironmentData {
5656
Type existential;
57+
GenericSignature parentSig;
5758
UUID uuid;
5859
};
5960

@@ -73,7 +74,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
7374
enum class Kind {
7475
/// A normal generic environment, determined only by its generic
7576
/// signature.
76-
Normal,
77+
Primary,
7778
/// A generic environment describing an opened existential archetype.
7879
OpenedExistential,
7980
/// A generic environment describing an opaque type archetype.
@@ -84,7 +85,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
8485

8586
private:
8687
mutable llvm::PointerIntPair<GenericSignature, 2, Kind> SignatureAndKind{
87-
GenericSignature(), Kind::Normal};
88+
GenericSignature(), Kind::Primary};
8889
NestedTypeStorage *nestedTypeStorage = nullptr;
8990

9091
friend TrailingObjects;
@@ -110,7 +111,8 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
110111

111112
explicit GenericEnvironment(GenericSignature signature);
112113
explicit GenericEnvironment(
113-
GenericSignature signature, Type existential, UUID uuid);
114+
GenericSignature signature,
115+
Type existential, GenericSignature parentSig, UUID uuid);
114116
explicit GenericEnvironment(
115117
GenericSignature signature, OpaqueTypeDecl *opaque, SubstitutionMap subs);
116118

@@ -143,6 +145,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
143145
/// Retrieve the UUID for an opened existential environment.
144146
UUID getOpenedExistentialUUID() const;
145147

148+
/// Retrieve the parent signature for an opened existential environment.
149+
GenericSignature getOpenedExistentialParentSignature() const;
150+
146151
/// Retrieve the opaque type declaration for a generic environment describing
147152
/// opaque types.
148153
OpaqueTypeDecl *getOpaqueTypeDecl() const;
@@ -151,36 +156,17 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
151156
/// create a generic environment.
152157
SubstitutionMap getOpaqueSubstitutions() const;
153158

154-
/// Create a new, "incomplete" generic environment that will be populated
155-
/// by calls to \c addMapping().
156-
static
157-
GenericEnvironment *getIncomplete(GenericSignature signature);
159+
/// Create a new, primary generic environment.
160+
static GenericEnvironment *forPrimary(GenericSignature signature);
158161

159162
/// Create a new generic environment for an opened existential.
160163
///
161-
/// This function uses the provided parent signature to construct a new
162-
/// signature suitable for use with an opened archetype. If you have an
163-
/// existing generic signature from e.g. deserialization use
164-
/// \c GenericEnvironment::forOpenedArchetypeSignature instead.
165-
///
166164
/// \param existential The subject existential type
167165
/// \param parentSig The signature of the context where this existential type is being opened
168166
/// \param uuid The unique identifier for this opened existential
169167
static GenericEnvironment *
170168
forOpenedExistential(Type existential, GenericSignature parentSig, UUID uuid);
171169

172-
/// Create a new generic environment for an opened existential.
173-
///
174-
/// It is unlikely you want to use this function.
175-
/// Call \c GenericEnvironment::forOpenedExistential instead.
176-
///
177-
/// \param existential The subject existential type
178-
/// \param signature The signature of the opened archetype
179-
/// \param uuid The unique identifier for this opened existential
180-
static GenericEnvironment *
181-
forOpenedArchetypeSignature(Type existential,
182-
GenericSignature signature, UUID uuid);
183-
184170
/// Create a new generic environment for an opaque type with the given set of
185171
/// outer substitutions.
186172
static GenericEnvironment *forOpaqueType(

include/swift/SIL/SILCloner.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,10 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
254254
assert(archetypeTy->isRoot());
255255

256256
auto sig = Builder.getFunction().getGenericSignature();
257-
auto existentialTy = archetypeTy->getExistentialType()->getCanonicalType();
258-
auto env = GenericEnvironment::forOpenedExistential(
259-
getOpASTType(existentialTy), sig, UUID::fromTime());
260-
auto interfaceTy = OpenedArchetypeType::getSelfInterfaceTypeFromContext(sig, existentialTy->getASTContext());
261-
auto replacementTy =
262-
env->mapTypeIntoContext(interfaceTy)
263-
->template castTo<OpenedArchetypeType>();
257+
auto origExistentialTy = archetypeTy->getExistentialType()
258+
->getCanonicalType();
259+
auto substExistentialTy = getOpASTType(origExistentialTy);
260+
auto replacementTy = OpenedArchetypeType::get(substExistentialTy, sig);
264261
registerOpenedExistentialRemapping(archetypeTy, replacementTy);
265262
}
266263

lib/AST/ASTContext.cpp

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4436,42 +4436,13 @@ CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
44364436
Type interfaceType,
44374437
GenericSignature parentSig,
44384438
Optional<UUID> knownID) {
4439-
assert(existential->isExistentialType());
44404439
assert(!interfaceType->hasArchetype() && "must be interface type");
4441-
// FIXME: Opened archetypes can't be transformed because the
4442-
// the identity of the archetype has to be preserved. This
4443-
// means that simplifying an opened archetype in the constraint
4444-
// system to replace type variables with fixed types is not
4445-
// yet supported. For now, assert that an opened archetype never
4446-
// contains type variables to catch cases where type variables
4447-
// would be applied to the type-checked AST.
4448-
assert(!existential->hasTypeVariable() &&
4449-
"opened existentials containing type variables cannot be simplified");
44504440

4451-
auto &ctx = existential->getASTContext();
4452-
auto &openedExistentialEnvironments =
4453-
ctx.getImpl().OpenedExistentialEnvironments;
4454-
// If we know the ID already...
4455-
if (knownID) {
4456-
// ... and we already have an archetype for that ID, return it.
4457-
auto found = openedExistentialEnvironments.find(*knownID);
4458-
4459-
if (found != openedExistentialEnvironments.end()) {
4460-
assert(found->second->getOpenedExistentialType()->isEqual(existential) &&
4461-
"Retrieved the wrong generic environment?");
4462-
auto result = found->second->mapTypeIntoContext(interfaceType)
4463-
->castTo<OpenedArchetypeType>();
4464-
return CanOpenedArchetypeType(result);
4465-
}
4466-
} else {
4467-
// Create a new ID.
4441+
if (!knownID)
44684442
knownID = UUID::fromTime();
4469-
}
44704443

4471-
/// Create a generic environment for this opened archetype.
4472-
auto genericEnv =
4444+
auto *genericEnv =
44734445
GenericEnvironment::forOpenedExistential(existential, parentSig, *knownID);
4474-
openedExistentialEnvironments[*knownID] = genericEnv;
44754446

44764447
// Map the interface type into that environment.
44774448
auto result = genericEnv->mapTypeIntoContext(interfaceType)
@@ -4637,8 +4608,7 @@ GenericSignature::get(TypeArrayView<GenericTypeParamType> params,
46374608
return newSig;
46384609
}
46394610

4640-
GenericEnvironment *GenericEnvironment::getIncomplete(
4641-
GenericSignature signature) {
4611+
GenericEnvironment *GenericEnvironment::forPrimary(GenericSignature signature) {
46424612
auto &ctx = signature->getASTContext();
46434613

46444614
// Allocate and construct the new environment.
@@ -4654,21 +4624,46 @@ GenericEnvironment *GenericEnvironment::getIncomplete(
46544624
GenericEnvironment *
46554625
GenericEnvironment::forOpenedExistential(
46564626
Type existential, GenericSignature parentSig, UUID uuid) {
4627+
assert(existential->isExistentialType());
4628+
// FIXME: Opened archetypes can't be transformed because the
4629+
// the identity of the archetype has to be preserved. This
4630+
// means that simplifying an opened archetype in the constraint
4631+
// system to replace type variables with fixed types is not
4632+
// yet supported. For now, assert that an opened archetype never
4633+
// contains type variables to catch cases where type variables
4634+
// would be applied to the type-checked AST.
4635+
assert(!existential->hasTypeVariable() &&
4636+
"opened existentials containing type variables cannot be simplified");
4637+
46574638
auto &ctx = existential->getASTContext();
4639+
4640+
auto &openedExistentialEnvironments =
4641+
ctx.getImpl().OpenedExistentialEnvironments;
4642+
auto found = openedExistentialEnvironments.find(uuid);
4643+
4644+
if (found != openedExistentialEnvironments.end()) {
4645+
auto *existingEnv = found->second;
4646+
assert(existingEnv->getOpenedExistentialType()->isEqual(existential));
4647+
assert(existingEnv->getOpenedExistentialParentSignature().getPointer() == parentSig.getPointer());
4648+
assert(existingEnv->getOpenedExistentialUUID() == uuid);
4649+
4650+
return existingEnv;
4651+
}
4652+
46584653
auto signature = ctx.getOpenedExistentialSignature(existential, parentSig);
4659-
return GenericEnvironment::forOpenedArchetypeSignature(existential, signature, uuid);
4660-
}
46614654

4662-
GenericEnvironment *GenericEnvironment::forOpenedArchetypeSignature(
4663-
Type existential, GenericSignature signature, UUID uuid) {
46644655
// Allocate and construct the new environment.
4665-
auto &ctx = existential->getASTContext();
46664656
unsigned numGenericParams = signature.getGenericParams().size();
46674657
size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap,
46684658
OpenedGenericEnvironmentData, Type>(
46694659
0, 0, 1, numGenericParams);
46704660
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
4671-
return new (mem) GenericEnvironment(signature, existential, uuid);
4661+
auto *genericEnv =
4662+
new (mem) GenericEnvironment(signature, existential, parentSig, uuid);
4663+
4664+
openedExistentialEnvironments[uuid] = genericEnv;
4665+
4666+
return genericEnv;
46724667
}
46734668

46744669
/// Create a new generic environment for an opaque type with the given set of

lib/AST/GenericEnvironment.cpp

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ using namespace swift;
2626
size_t GenericEnvironment::numTrailingObjects(
2727
OverloadToken<OpaqueTypeDecl *>) const {
2828
switch (getKind()) {
29-
case Kind::Normal:
29+
case Kind::Primary:
3030
case Kind::OpenedExistential:
3131
return 0;
3232

@@ -38,7 +38,7 @@ size_t GenericEnvironment::numTrailingObjects(
3838
size_t GenericEnvironment::numTrailingObjects(
3939
OverloadToken<SubstitutionMap>) const {
4040
switch (getKind()) {
41-
case Kind::Normal:
41+
case Kind::Primary:
4242
case Kind::OpenedExistential:
4343
return 0;
4444

@@ -50,7 +50,7 @@ size_t GenericEnvironment::numTrailingObjects(
5050
size_t GenericEnvironment::numTrailingObjects(
5151
OverloadToken<OpenedGenericEnvironmentData>) const {
5252
switch (getKind()) {
53-
case Kind::Normal:
53+
case Kind::Primary:
5454
case Kind::Opaque:
5555
return 0;
5656

@@ -104,20 +104,27 @@ UUID GenericEnvironment::getOpenedExistentialUUID() const {
104104
return getTrailingObjects<OpenedGenericEnvironmentData>()->uuid;
105105
}
106106

107+
GenericSignature
108+
GenericEnvironment::getOpenedExistentialParentSignature() const {
109+
assert(getKind() == Kind::OpenedExistential);
110+
return getTrailingObjects<OpenedGenericEnvironmentData>()->parentSig;
111+
}
112+
107113
GenericEnvironment::GenericEnvironment(GenericSignature signature)
108-
: SignatureAndKind(signature, Kind::Normal)
114+
: SignatureAndKind(signature, Kind::Primary)
109115
{
110116
// Clear out the memory that holds the context types.
111117
std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(),
112118
Type());
113119
}
114120

115121
GenericEnvironment::GenericEnvironment(
116-
GenericSignature signature, Type existential, UUID uuid)
122+
GenericSignature signature,
123+
Type existential, GenericSignature parentSig, UUID uuid)
117124
: SignatureAndKind(signature, Kind::OpenedExistential)
118125
{
119126
new (getTrailingObjects<OpenedGenericEnvironmentData>())
120-
OpenedGenericEnvironmentData{ existential, uuid };
127+
OpenedGenericEnvironmentData{ existential, parentSig, uuid };
121128

122129
// Clear out the memory that holds the context types.
123130
std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(),
@@ -209,7 +216,7 @@ struct SubstituteOuterFromSubstitutionMap {
209216

210217
Type GenericEnvironment::maybeApplyOpaqueTypeSubstitutions(Type type) const {
211218
switch (getKind()) {
212-
case Kind::Normal:
219+
case Kind::Primary:
213220
case Kind::OpenedExistential:
214221
return type;
215222

@@ -273,15 +280,6 @@ auto GenericEnvironment::getOrCreateNestedTypeStorage() -> NestedTypeStorage & {
273280
return *nestedTypeStorage;
274281
}
275282

276-
static Type stripBoundDependentMemberTypes(Type t) {
277-
if (auto *depMemTy = t->getAs<DependentMemberType>()) {
278-
return DependentMemberType::get(
279-
stripBoundDependentMemberTypes(depMemTy->getBase()),
280-
depMemTy->getName());
281-
}
282-
283-
return t;
284-
}
285283
Type
286284
GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
287285
auto genericSig = getGenericSignature();
@@ -292,7 +290,7 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
292290
/// Substitute a type for the purpose of requirements.
293291
auto substForRequirements = [&](Type type) {
294292
switch (getKind()) {
295-
case Kind::Normal:
293+
case Kind::Primary:
296294
case Kind::OpenedExistential:
297295
if (type->hasTypeParameter()) {
298296
return mapTypeIntoContext(type, conformanceLookupFn);
@@ -315,12 +313,11 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
315313
// First, write an ErrorType to the location where this type is cached,
316314
// to catch re-entrant lookups that might arise from an invalid generic
317315
// signature (eg, <X where X == Array<X>>).
318-
CanDependentMemberType nestedDependentMemberType;
316+
CanDependentMemberType nestedType;
319317
GenericTypeParamType *genericParam = nullptr;
320318
if (auto depMemTy = requirements.anchor->getAs<DependentMemberType>()) {
321-
nestedDependentMemberType = cast<DependentMemberType>(
322-
stripBoundDependentMemberTypes(depMemTy)->getCanonicalType());
323-
auto &entry = getOrCreateNestedTypeStorage()[nestedDependentMemberType];
319+
nestedType = cast<DependentMemberType>(depMemTy->getCanonicalType());
320+
auto &entry = getOrCreateNestedTypeStorage()[nestedType];
324321
if (entry)
325322
return entry;
326323

@@ -342,13 +339,15 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
342339

343340
Type result;
344341

345-
if (requirements.anchor->getRootGenericParam()->isTypeSequence()) {
342+
auto rootGP = requirements.anchor->getRootGenericParam();
343+
if (rootGP->isTypeSequence()) {
344+
assert(getKind() == Kind::Primary);
346345
result = SequenceArchetypeType::get(ctx, this, requirements.anchor,
347346
requirements.protos, superclass,
348347
requirements.layout);
349348
} else {
350349
switch (getKind()) {
351-
case Kind::Normal:
350+
case Kind::Primary:
352351
result = PrimaryArchetypeType::getNew(ctx, this, requirements.anchor,
353352
requirements.protos, superclass,
354353
requirements.layout);
@@ -384,7 +383,6 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
384383
// If the anchor type isn't rooted in a generic parameter that
385384
// represents an opaque declaration, then apply the outer substitutions.
386385
// It would be incorrect to build an opaque type archetype here.
387-
auto rootGP = requirements.anchor->getRootGenericParam();
388386
unsigned opaqueDepth =
389387
getOpaqueTypeDecl()->getOpaqueGenericParams().front()->getDepth();
390388
if (rootGP->getDepth() < opaqueDepth) {
@@ -403,7 +401,7 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
403401
if (genericParam)
404402
addMapping(genericParam, result);
405403
else
406-
getOrCreateNestedTypeStorage()[nestedDependentMemberType] = result;
404+
getOrCreateNestedTypeStorage()[nestedType] = result;
407405

408406
return result;
409407
}

lib/AST/GenericSignature.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ GenericEnvironment *GenericSignature::getGenericEnvironment() const {
267267
GenericEnvironment *GenericSignatureImpl::getGenericEnvironment() const {
268268
if (GenericEnv == nullptr) {
269269
const auto impl = const_cast<GenericSignatureImpl *>(this);
270-
impl->GenericEnv = GenericEnvironment::getIncomplete(this);
270+
impl->GenericEnv = GenericEnvironment::forPrimary(this);
271271
}
272272

273273
return GenericEnv;

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ OTHER(TOP_LEVEL_CODE_DECL_CONTEXT, 112)
167167
OTHER(GENERIC_PARAM_LIST, 120)
168168
OTHER(GENERIC_SIGNATURE, 121)
169169
OTHER(REQUIREMENT_SIGNATURE, 122)
170-
// 123 is unused; was LAYOUT_REQUIREMENT
170+
OTHER(GENERIC_ENVIRONMENT, 123)
171171
OTHER(BUILTIN_PROTOCOL_CONFORMANCE, 124)
172172
OTHER(SIL_GENERIC_SIGNATURE, 125)
173173
OTHER(SUBSTITUTION_MAP, 126)

0 commit comments

Comments
 (0)