Skip to content

Commit b36f37c

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 7a97036 commit b36f37c

14 files changed

+165
-51
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 existential.
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;
@@ -156,29 +161,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
156161

157162
/// Create a new generic environment for an opened existential.
158163
///
159-
/// This function uses the provided parent signature to construct a new
160-
/// signature suitable for use with an opened archetype. If you have an
161-
/// existing generic signature from e.g. deserialization use
162-
/// \c GenericEnvironment::forOpenedArchetypeSignature instead.
163-
///
164164
/// \param existential The subject existential type
165165
/// \param parentSig The signature of the context where this existential type is being opened
166166
/// \param uuid The unique identifier for this opened existential
167167
static GenericEnvironment *
168168
forOpenedExistential(Type existential, GenericSignature parentSig, UUID uuid);
169169

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

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4655,19 +4655,14 @@ GenericEnvironment::forOpenedExistential(
46554655
Type existential, GenericSignature parentSig, UUID uuid) {
46564656
auto &ctx = existential->getASTContext();
46574657
auto signature = ctx.getOpenedExistentialSignature(existential, parentSig);
4658-
return GenericEnvironment::forOpenedArchetypeSignature(existential, signature, uuid);
4659-
}
46604658

4661-
GenericEnvironment *GenericEnvironment::forOpenedArchetypeSignature(
4662-
Type existential, GenericSignature signature, UUID uuid) {
46634659
// Allocate and construct the new environment.
4664-
auto &ctx = existential->getASTContext();
46654660
unsigned numGenericParams = signature.getGenericParams().size();
46664661
size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap,
46674662
OpenedGenericEnvironmentData, Type>(
46684663
0, 0, 1, numGenericParams);
46694664
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
4670-
return new (mem) GenericEnvironment(signature, existential, uuid);
4665+
return new (mem) GenericEnvironment(signature, existential, parentSig, uuid);
46714666
}
46724667

46734668
/// 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::Primary)
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
@@ -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)

lib/Serialization/Deserialization.cpp

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,53 @@ ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
11881188
return signature;
11891189
}
11901190

1191+
Expected<GenericEnvironment *>
1192+
ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID) {
1193+
using namespace decls_block;
1194+
1195+
assert(ID <= GenericEnvironments.size() &&
1196+
"invalid GenericEnvironment ID");
1197+
auto &envOffset = GenericEnvironments[ID-1];
1198+
1199+
// If we've already deserialized this generic environment, return it.
1200+
if (envOffset.isComplete())
1201+
return envOffset.get();
1202+
1203+
// Read the generic environment.
1204+
BCOffsetRAII restoreOffset(DeclTypeCursor);
1205+
fatalIfNotSuccess(DeclTypeCursor.JumpToBit(envOffset));
1206+
1207+
llvm::BitstreamEntry entry =
1208+
fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
1209+
if (entry.Kind != llvm::BitstreamEntry::Record)
1210+
fatal();
1211+
1212+
StringRef blobData;
1213+
SmallVector<uint64_t, 8> scratch;
1214+
unsigned recordID = fatalIfUnexpected(
1215+
DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
1216+
if (recordID != GENERIC_ENVIRONMENT)
1217+
fatal();
1218+
1219+
GenericSignatureID parentSigID;
1220+
TypeID existentialID;
1221+
GenericEnvironmentLayout::readRecord(scratch, existentialID, parentSigID);
1222+
1223+
auto existentialTypeOrError = getTypeChecked(existentialID);
1224+
if (!existentialTypeOrError)
1225+
return existentialTypeOrError.takeError();
1226+
1227+
auto parentSigOrError = getGenericSignatureChecked(parentSigID);
1228+
if (!parentSigOrError)
1229+
return parentSigOrError.takeError();
1230+
1231+
auto *genericEnv = GenericEnvironment::forOpenedExistential(
1232+
existentialTypeOrError.get(), parentSigOrError.get(), UUID::fromTime());
1233+
envOffset = genericEnv;
1234+
1235+
return genericEnv;
1236+
}
1237+
11911238
SubstitutionMap ModuleFile::getSubstitutionMap(
11921239
serialization::SubstitutionMapID id) {
11931240
auto map = getSubstitutionMapChecked(id);
@@ -5747,29 +5794,22 @@ Expected<Type> DESERIALIZE_TYPE(PRIMARY_ARCHETYPE_TYPE)(
57475794

57485795
Expected<Type> DESERIALIZE_TYPE(OPENED_ARCHETYPE_TYPE)(
57495796
ModuleFile &MF, SmallVectorImpl<uint64_t> &scratch, StringRef blobData) {
5750-
TypeID existentialID;
57515797
TypeID interfaceID;
5752-
GenericSignatureID sigID;
5798+
GenericEnvironmentID genericEnvID;
57535799

5754-
decls_block::OpenedArchetypeTypeLayout::readRecord(scratch, existentialID,
5755-
interfaceID, sigID);
5756-
5757-
auto sigOrError = MF.getGenericSignatureChecked(sigID);
5758-
if (!sigOrError)
5759-
return sigOrError.takeError();
5800+
decls_block::OpenedArchetypeTypeLayout::readRecord(scratch,
5801+
interfaceID,
5802+
genericEnvID);
57605803

57615804
auto interfaceTypeOrError = MF.getTypeChecked(interfaceID);
57625805
if (!interfaceTypeOrError)
57635806
return interfaceTypeOrError.takeError();
57645807

5765-
auto existentialTypeOrError = MF.getTypeChecked(existentialID);
5766-
if (!existentialTypeOrError)
5767-
return existentialTypeOrError.takeError();
5808+
auto envOrError = MF.getGenericEnvironmentChecked(genericEnvID);
5809+
if (!envOrError)
5810+
return envOrError.takeError();
57685811

5769-
auto env = GenericEnvironment::forOpenedArchetypeSignature(
5770-
existentialTypeOrError.get(), sigOrError.get(), UUID::fromTime());
5771-
return env->mapTypeIntoContext(interfaceTypeOrError.get())
5772-
->castTo<OpenedArchetypeType>();
5812+
return envOrError.get()->mapTypeIntoContext(interfaceTypeOrError.get());
57735813
}
57745814

57755815
Expected<Type> DESERIALIZE_TYPE(OPAQUE_ARCHETYPE_TYPE)(

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
@@ -259,6 +259,9 @@ class ModuleFile
259259
/// Generic signatures referenced by this module.
260260
MutableArrayRef<Serialized<GenericSignature>> GenericSignatures;
261261

262+
/// Generic environments referenced by this module.
263+
MutableArrayRef<Serialized<GenericEnvironment *>> GenericEnvironments;
264+
262265
/// Substitution maps referenced by this module.
263266
MutableArrayRef<Serialized<SubstitutionMap>> SubstitutionMaps;
264267

@@ -862,6 +865,10 @@ class ModuleFile
862865
llvm::Expected<GenericSignature>
863866
getGenericSignatureChecked(serialization::GenericSignatureID ID);
864867

868+
/// Returns the generic environment for the given ID or the first error.
869+
llvm::Expected<GenericEnvironment *>
870+
getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID);
871+
865872
/// Returns the substitution map for the given ID, deserializing it if
866873
/// needed.
867874
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
@@ -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 = 700; // explicit_copy_addr
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 701; // opened archetype serialization
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -145,6 +145,9 @@ using ProtocolConformanceIDField = DeclIDField;
145145
using GenericSignatureID = DeclID;
146146
using GenericSignatureIDField = DeclIDField;
147147

148+
using GenericEnvironmentID = unsigned;
149+
using GenericEnvironmentIDField = BCFixed<32>;
150+
148151
// SubstitutionMapID must be the same as DeclID because it is stored in the
149152
// same way.
150153
using SubstitutionMapID = DeclID;
@@ -1122,9 +1125,8 @@ namespace decls_block {
11221125

11231126
TYPE_LAYOUT(OpenedArchetypeTypeLayout,
11241127
OPENED_ARCHETYPE_TYPE,
1125-
TypeIDField, // the existential type
1126-
TypeIDField, // the interface type
1127-
GenericSignatureIDField // generic signature
1128+
TypeIDField, // the interface type
1129+
GenericEnvironmentIDField // generic environment ID
11281130
);
11291131

11301132
TYPE_LAYOUT(OpaqueArchetypeTypeLayout,
@@ -1691,6 +1693,12 @@ namespace decls_block {
16911693
BCArray<TypeIDField> // generic parameter types
16921694
>;
16931695

1696+
using GenericEnvironmentLayout = BCRecordLayout<
1697+
GENERIC_ENVIRONMENT,
1698+
TypeIDField, // existential type
1699+
GenericSignatureIDField // parent signature
1700+
>;
1701+
16941702
using SubstitutionMapLayout = BCRecordLayout<
16951703
SUBSTITUTION_MAP,
16961704
GenericSignatureIDField, // generic signature
@@ -2178,6 +2186,7 @@ namespace index_block {
21782186
LOCAL_TYPE_DECLS,
21792187
OPAQUE_RETURN_TYPE_DECLS,
21802188
GENERIC_SIGNATURE_OFFSETS,
2189+
GENERIC_ENVIRONMENT_OFFSETS,
21812190
PROTOCOL_CONFORMANCE_OFFSETS,
21822191
SIL_LAYOUT_OFFSETS,
21832192

0 commit comments

Comments
 (0)