Skip to content

Commit aa103c9

Browse files
committed
Serialization: Preserve identity of opened generic environments
We used to create a new environment for each opened archetype, which is incorrect when deserializing a nested type of another opened archetype.
1 parent 9ef092c commit aa103c9

14 files changed

+164
-50
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 6 additions & 18 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 existentiak.
5555
struct OpenedGenericEnvironmentData {
5656
Type existential;
57+
GenericSignature parentSig;
5758
UUID uuid;
5859
};
5960

@@ -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;
@@ -158,29 +163,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
158163

159164
/// Create a new generic environment for an opened existential.
160165
///
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-
///
166166
/// \param existential The subject existential type
167167
/// \param parentSig The signature of the context where this existential type is being opened
168168
/// \param uuid The unique identifier for this opened existential
169169
static GenericEnvironment *
170170
forOpenedExistential(Type existential, GenericSignature parentSig, UUID uuid);
171171

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-
184172
/// Create a new generic environment for an opaque type with the given set of
185173
/// outer substitutions.
186174
static GenericEnvironment *forOpaqueType(

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4679,19 +4679,14 @@ GenericEnvironment::forOpenedExistential(
46794679
Type existential, GenericSignature parentSig, UUID uuid) {
46804680
auto &ctx = existential->getASTContext();
46814681
auto signature = ctx.getOpenedArchetypeSignature(existential, parentSig);
4682-
return GenericEnvironment::forOpenedArchetypeSignature(existential, signature, uuid);
4683-
}
46844682

4685-
GenericEnvironment *GenericEnvironment::forOpenedArchetypeSignature(
4686-
Type existential, GenericSignature signature, UUID uuid) {
46874683
// Allocate and construct the new environment.
4688-
auto &ctx = existential->getASTContext();
46894684
unsigned numGenericParams = signature.getGenericParams().size();
46904685
size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap,
46914686
OpenedGenericEnvironmentData, Type>(
46924687
0, 0, 1, numGenericParams);
46934688
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
4694-
return new (mem) GenericEnvironment(signature, existential, uuid);
4689+
return new (mem) GenericEnvironment(signature, existential, parentSig, uuid);
46954690
}
46964691

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

lib/AST/GenericEnvironment.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ 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)
108114
: SignatureAndKind(signature, Kind::Normal)
109115
{
@@ -113,11 +119,12 @@ GenericEnvironment::GenericEnvironment(GenericSignature signature)
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(),

lib/Serialization/DeclTypeRecordNodes.def

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

lib/Serialization/Deserialization.cpp

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,53 @@ ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
11811181
return signature;
11821182
}
11831183

1184+
Expected<GenericEnvironment *>
1185+
ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID) {
1186+
using namespace decls_block;
1187+
1188+
assert(ID <= GenericEnvironments.size() &&
1189+
"invalid GenericEnvironment ID");
1190+
auto &envOffset = GenericEnvironments[ID-1];
1191+
1192+
// If we've already deserialized this generic environment, return it.
1193+
if (envOffset.isComplete())
1194+
return envOffset.get();
1195+
1196+
// Read the generic environment.
1197+
BCOffsetRAII restoreOffset(DeclTypeCursor);
1198+
fatalIfNotSuccess(DeclTypeCursor.JumpToBit(envOffset));
1199+
1200+
llvm::BitstreamEntry entry =
1201+
fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
1202+
if (entry.Kind != llvm::BitstreamEntry::Record)
1203+
fatal();
1204+
1205+
StringRef blobData;
1206+
SmallVector<uint64_t, 8> scratch;
1207+
unsigned recordID = fatalIfUnexpected(
1208+
DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
1209+
if (recordID != GENERIC_ENVIRONMENT)
1210+
fatal();
1211+
1212+
GenericSignatureID parentSigID;
1213+
TypeID existentialID;
1214+
GenericEnvironmentLayout::readRecord(scratch, existentialID, parentSigID);
1215+
1216+
auto existentialTypeOrError = getTypeChecked(existentialID);
1217+
if (!existentialTypeOrError)
1218+
return existentialTypeOrError.takeError();
1219+
1220+
auto parentSigOrError = getGenericSignatureChecked(parentSigID);
1221+
if (!parentSigOrError)
1222+
return parentSigOrError.takeError();
1223+
1224+
auto *genericEnv = GenericEnvironment::forOpenedExistential(
1225+
existentialTypeOrError.get(), parentSigOrError.get(), UUID::fromTime());
1226+
envOffset = genericEnv;
1227+
1228+
return genericEnv;
1229+
}
1230+
11841231
SubstitutionMap ModuleFile::getSubstitutionMap(
11851232
serialization::SubstitutionMapID id) {
11861233
auto map = getSubstitutionMapChecked(id);
@@ -5709,28 +5756,21 @@ class TypeDeserializer {
57095756

57105757
Expected<Type> deserializeOpenedArchetypeType(ArrayRef<uint64_t> scratch,
57115758
StringRef blobData) {
5712-
TypeID existentialID;
57135759
TypeID interfaceID;
5714-
GenericSignatureID sigID;
5715-
5716-
decls_block::OpenedArchetypeTypeLayout::readRecord(scratch, existentialID,
5717-
interfaceID, sigID);
5760+
GenericEnvironmentID genericEnvID;
57185761

5719-
auto sigOrError = MF.getGenericSignatureChecked(sigID);
5720-
if (!sigOrError)
5721-
return sigOrError.takeError();
5762+
decls_block::OpenedArchetypeTypeLayout::readRecord(scratch,
5763+
interfaceID, genericEnvID);
57225764

57235765
auto interfaceTypeOrError = MF.getTypeChecked(interfaceID);
57245766
if (!interfaceTypeOrError)
57255767
return interfaceTypeOrError.takeError();
57265768

5727-
auto existentialTypeOrError = MF.getTypeChecked(existentialID);
5728-
if (!existentialTypeOrError)
5729-
return existentialTypeOrError.takeError();
5769+
auto envOrError = MF.getGenericEnvironmentChecked(genericEnvID);
5770+
if (!envOrError)
5771+
return envOrError.takeError();
57305772

5731-
auto env = GenericEnvironment::forOpenedArchetypeSignature(
5732-
existentialTypeOrError.get(), sigOrError.get(), UUID::fromTime());
5733-
return env->mapTypeIntoContext(interfaceTypeOrError.get())
5773+
return envOrError.get()->mapTypeIntoContext(interfaceTypeOrError.get())
57345774
->castTo<OpenedArchetypeType>();
57355775
}
57365776

lib/Serialization/ModuleFile.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ ModuleFile::ModuleFile(std::shared_ptr<const ModuleFileSharedCore> core)
113113
allocateBuffer(Types, core->Types);
114114
allocateBuffer(ClangTypes, core->ClangTypes);
115115
allocateBuffer(GenericSignatures, core->GenericSignatures);
116+
allocateBuffer(GenericEnvironments, core->GenericEnvironments);
116117
allocateBuffer(SubstitutionMaps, core->SubstitutionMaps);
117118
allocateBuffer(Identifiers, core->Identifiers);
118119
}

lib/Serialization/ModuleFile.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ class ModuleFile
256256
/// Generic signatures referenced by this module.
257257
MutableArrayRef<Serialized<GenericSignature>> GenericSignatures;
258258

259+
/// Generic environments referenced by this module.
260+
MutableArrayRef<Serialized<GenericEnvironment *>> GenericEnvironments;
261+
259262
/// Substitution maps referenced by this module.
260263
MutableArrayRef<Serialized<SubstitutionMap>> SubstitutionMaps;
261264

@@ -859,6 +862,10 @@ class ModuleFile
859862
llvm::Expected<GenericSignature>
860863
getGenericSignatureChecked(serialization::GenericSignatureID ID);
861864

865+
/// Returns the generic environment for the given ID or the first error.
866+
llvm::Expected<GenericEnvironment *>
867+
getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID);
868+
862869
/// Returns the substitution map for the given ID, deserializing it if
863870
/// needed.
864871
SubstitutionMap getSubstitutionMap(serialization::SubstitutionMapID id);

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,10 @@ bool ModuleFileSharedCore::readIndexBlock(llvm::BitstreamCursor &cursor) {
839839
assert(blobData.empty());
840840
allocateBuffer(GenericSignatures, scratch);
841841
break;
842+
case index_block::GENERIC_ENVIRONMENT_OFFSETS:
843+
assert(blobData.empty());
844+
allocateBuffer(GenericEnvironments, scratch);
845+
break;
842846
case index_block::SUBSTITUTION_MAP_OFFSETS:
843847
assert(blobData.empty());
844848
allocateBuffer(SubstitutionMaps, scratch);

lib/Serialization/ModuleFileSharedCore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ class ModuleFileSharedCore {
218218
/// Generic signatures referenced by this module.
219219
ArrayRef<RawBitOffset> GenericSignatures;
220220

221+
/// Generic environments referenced by this module.
222+
ArrayRef<RawBitOffset> GenericEnvironments;
223+
221224
/// Substitution maps referenced by this module.
222225
ArrayRef<RawBitOffset> SubstitutionMaps;
223226

lib/Serialization/ModuleFormat.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 698; // revert selector table changes
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 699; // opened archetype serialization
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///
@@ -143,6 +143,9 @@ using ProtocolConformanceIDField = DeclIDField;
143143
using GenericSignatureID = DeclID;
144144
using GenericSignatureIDField = DeclIDField;
145145

146+
using GenericEnvironmentID = unsigned;
147+
using GenericEnvironmentIDField = BCFixed<32>;
148+
146149
// SubstitutionMapID must be the same as DeclID because it is stored in the
147150
// same way.
148151
using SubstitutionMapID = DeclID;
@@ -1077,9 +1080,8 @@ namespace decls_block {
10771080

10781081
using OpenedArchetypeTypeLayout = BCRecordLayout<
10791082
OPENED_ARCHETYPE_TYPE,
1080-
TypeIDField, // the existential type
1081-
TypeIDField, // the interface type
1082-
GenericSignatureIDField // generic signature
1083+
TypeIDField, // the interface type
1084+
GenericEnvironmentIDField // generic environment ID
10831085
>;
10841086

10851087
using OpaqueArchetypeTypeLayout = BCRecordLayout<
@@ -1636,6 +1638,12 @@ namespace decls_block {
16361638
BCArray<TypeIDField> // generic parameter types
16371639
>;
16381640

1641+
using GenericEnvironmentLayout = BCRecordLayout<
1642+
GENERIC_ENVIRONMENT,
1643+
TypeIDField, // existential type
1644+
GenericSignatureIDField // parent signature
1645+
>;
1646+
16391647
using SubstitutionMapLayout = BCRecordLayout<
16401648
SUBSTITUTION_MAP,
16411649
GenericSignatureIDField, // generic signature
@@ -2119,6 +2127,7 @@ namespace index_block {
21192127
LOCAL_TYPE_DECLS,
21202128
OPAQUE_RETURN_TYPE_DECLS,
21212129
GENERIC_SIGNATURE_OFFSETS,
2130+
GENERIC_ENVIRONMENT_OFFSETS,
21222131
PROTOCOL_CONFORMANCE_OFFSETS,
21232132
SIL_LAYOUT_OFFSETS,
21242133

lib/Serialization/Serialization.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,13 @@ Serializer::addGenericSignatureRef(GenericSignature sig) {
594594
return GenericSignaturesToSerialize.addRef(sig);
595595
}
596596

597+
GenericEnvironmentID
598+
Serializer::addGenericEnvironmentRef(GenericEnvironment *env) {
599+
if (!env)
600+
return 0;
601+
return GenericEnvironmentsToSerialize.addRef(env);
602+
}
603+
597604
SubstitutionMapID
598605
Serializer::addSubstitutionMapRef(SubstitutionMap substitutions) {
599606
return SubstitutionMapsToSerialize.addRef(substitutions);
@@ -878,6 +885,7 @@ void Serializer::writeBlockInfoBlock() {
878885
BLOCK_RECORD(index_block, ENTRY_POINT);
879886
BLOCK_RECORD(index_block, LOCAL_DECL_CONTEXT_OFFSETS);
880887
BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS);
888+
BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
881889
BLOCK_RECORD(index_block, SUBSTITUTION_MAP_OFFSETS);
882890
BLOCK_RECORD(index_block, CLANG_TYPE_OFFSETS);
883891
BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS);
@@ -1490,6 +1498,20 @@ void Serializer::writeASTBlockEntity(GenericSignature sig) {
14901498
}
14911499
}
14921500

1501+
void Serializer::writeASTBlockEntity(const GenericEnvironment *genericEnv) {
1502+
using namespace decls_block;
1503+
1504+
assert(GenericEnvironmentsToSerialize.hasRef(genericEnv));
1505+
1506+
auto existentialTypeID = addTypeRef(genericEnv->getOpenedExistentialType());
1507+
auto parentSig = genericEnv->getOpenedExistentialParentSignature();
1508+
auto parentSigID = addGenericSignatureRef(parentSig);
1509+
1510+
auto genericEnvAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
1511+
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, genericEnvAbbrCode,
1512+
existentialTypeID, parentSigID);
1513+
}
1514+
14931515
void Serializer::writeASTBlockEntity(const SubstitutionMap substitutions) {
14941516
using namespace decls_block;
14951517
assert(substitutions);
@@ -4592,14 +4614,12 @@ class Serializer::TypeSerializer : public TypeVisitor<TypeSerializer> {
45924614

45934615
void visitOpenedArchetypeType(const OpenedArchetypeType *archetypeTy) {
45944616
using namespace decls_block;
4595-
auto sig = archetypeTy->getGenericEnvironment()->getGenericSignature();
4596-
auto existentialTypeID = S.addTypeRef(archetypeTy->getExistentialType());
45974617
auto interfaceTypeID = S.addTypeRef(archetypeTy->getInterfaceType());
4598-
auto sigID = S.addGenericSignatureRef(sig);
4618+
auto genericEnvID = S.addGenericEnvironmentRef(
4619+
archetypeTy->getGenericEnvironment());
45994620
unsigned abbrCode = S.DeclTypeAbbrCodes[OpenedArchetypeTypeLayout::Code];
46004621
OpenedArchetypeTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
4601-
existentialTypeID, interfaceTypeID,
4602-
sigID);
4622+
interfaceTypeID, genericEnvID);
46034623
}
46044624

46054625
void
@@ -5090,6 +5110,7 @@ void Serializer::writeAllDeclsAndTypes() {
50905110
registerDeclTypeAbbr<InlinableBodyTextLayout>();
50915111
registerDeclTypeAbbr<GenericParamListLayout>();
50925112
registerDeclTypeAbbr<GenericSignatureLayout>();
5113+
registerDeclTypeAbbr<GenericEnvironmentLayout>();
50935114
registerDeclTypeAbbr<RequirementSignatureLayout>();
50945115
registerDeclTypeAbbr<SILGenericSignatureLayout>();
50955116
registerDeclTypeAbbr<SubstitutionMapLayout>();
@@ -5143,6 +5164,8 @@ void Serializer::writeAllDeclsAndTypes() {
51435164
writeASTBlockEntitiesIfNeeded(LocalDeclContextsToSerialize);
51445165
wroteSomething |=
51455166
writeASTBlockEntitiesIfNeeded(GenericSignaturesToSerialize);
5167+
wroteSomething |=
5168+
writeASTBlockEntitiesIfNeeded(GenericEnvironmentsToSerialize);
51465169
wroteSomething |=
51475170
writeASTBlockEntitiesIfNeeded(SubstitutionMapsToSerialize);
51485171
wroteSomething |=
@@ -5746,6 +5769,7 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
57465769
writeOffsets(Offsets, ClangTypesToSerialize);
57475770
writeOffsets(Offsets, LocalDeclContextsToSerialize);
57485771
writeOffsets(Offsets, GenericSignaturesToSerialize);
5772+
writeOffsets(Offsets, GenericEnvironmentsToSerialize);
57495773
writeOffsets(Offsets, SubstitutionMapsToSerialize);
57505774
writeOffsets(Offsets, ConformancesToSerialize);
57515775
writeOffsets(Offsets, SILLayoutsToSerialize);

0 commit comments

Comments
 (0)