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:
Slava Pestov
2022-08-11 23:44:18 -04:00
parent 7a970367fd
commit b36f37cc72
14 changed files with 165 additions and 51 deletions

View File

@@ -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)(