mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
This commit is contained in:
@@ -1188,6 +1188,53 @@ ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
|
||||
return signature;
|
||||
}
|
||||
|
||||
Expected<GenericEnvironment *>
|
||||
ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID) {
|
||||
using namespace decls_block;
|
||||
|
||||
assert(ID <= GenericEnvironments.size() &&
|
||||
"invalid GenericEnvironment ID");
|
||||
auto &envOffset = GenericEnvironments[ID-1];
|
||||
|
||||
// If we've already deserialized this generic environment, return it.
|
||||
if (envOffset.isComplete())
|
||||
return envOffset.get();
|
||||
|
||||
// Read the generic environment.
|
||||
BCOffsetRAII restoreOffset(DeclTypeCursor);
|
||||
fatalIfNotSuccess(DeclTypeCursor.JumpToBit(envOffset));
|
||||
|
||||
llvm::BitstreamEntry entry =
|
||||
fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
|
||||
if (entry.Kind != llvm::BitstreamEntry::Record)
|
||||
fatal();
|
||||
|
||||
StringRef blobData;
|
||||
SmallVector<uint64_t, 8> scratch;
|
||||
unsigned recordID = fatalIfUnexpected(
|
||||
DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
|
||||
if (recordID != GENERIC_ENVIRONMENT)
|
||||
fatal();
|
||||
|
||||
GenericSignatureID parentSigID;
|
||||
TypeID existentialID;
|
||||
GenericEnvironmentLayout::readRecord(scratch, existentialID, parentSigID);
|
||||
|
||||
auto existentialTypeOrError = getTypeChecked(existentialID);
|
||||
if (!existentialTypeOrError)
|
||||
return existentialTypeOrError.takeError();
|
||||
|
||||
auto parentSigOrError = getGenericSignatureChecked(parentSigID);
|
||||
if (!parentSigOrError)
|
||||
return parentSigOrError.takeError();
|
||||
|
||||
auto *genericEnv = GenericEnvironment::forOpenedExistential(
|
||||
existentialTypeOrError.get(), parentSigOrError.get(), UUID::fromTime());
|
||||
envOffset = genericEnv;
|
||||
|
||||
return genericEnv;
|
||||
}
|
||||
|
||||
SubstitutionMap ModuleFile::getSubstitutionMap(
|
||||
serialization::SubstitutionMapID id) {
|
||||
auto map = getSubstitutionMapChecked(id);
|
||||
@@ -5747,29 +5794,22 @@ Expected<Type> DESERIALIZE_TYPE(PRIMARY_ARCHETYPE_TYPE)(
|
||||
|
||||
Expected<Type> DESERIALIZE_TYPE(OPENED_ARCHETYPE_TYPE)(
|
||||
ModuleFile &MF, SmallVectorImpl<uint64_t> &scratch, StringRef blobData) {
|
||||
TypeID existentialID;
|
||||
TypeID interfaceID;
|
||||
GenericSignatureID sigID;
|
||||
GenericEnvironmentID genericEnvID;
|
||||
|
||||
decls_block::OpenedArchetypeTypeLayout::readRecord(scratch, existentialID,
|
||||
interfaceID, sigID);
|
||||
|
||||
auto sigOrError = MF.getGenericSignatureChecked(sigID);
|
||||
if (!sigOrError)
|
||||
return sigOrError.takeError();
|
||||
decls_block::OpenedArchetypeTypeLayout::readRecord(scratch,
|
||||
interfaceID,
|
||||
genericEnvID);
|
||||
|
||||
auto interfaceTypeOrError = MF.getTypeChecked(interfaceID);
|
||||
if (!interfaceTypeOrError)
|
||||
return interfaceTypeOrError.takeError();
|
||||
|
||||
auto existentialTypeOrError = MF.getTypeChecked(existentialID);
|
||||
if (!existentialTypeOrError)
|
||||
return existentialTypeOrError.takeError();
|
||||
auto envOrError = MF.getGenericEnvironmentChecked(genericEnvID);
|
||||
if (!envOrError)
|
||||
return envOrError.takeError();
|
||||
|
||||
auto env = GenericEnvironment::forOpenedArchetypeSignature(
|
||||
existentialTypeOrError.get(), sigOrError.get(), UUID::fromTime());
|
||||
return env->mapTypeIntoContext(interfaceTypeOrError.get())
|
||||
->castTo<OpenedArchetypeType>();
|
||||
return envOrError.get()->mapTypeIntoContext(interfaceTypeOrError.get());
|
||||
}
|
||||
|
||||
Expected<Type> DESERIALIZE_TYPE(OPAQUE_ARCHETYPE_TYPE)(
|
||||
|
||||
Reference in New Issue
Block a user