[Serialization] Make serialization of witnesses deterministic.

Serialization of the requirement-to-synthetic-environment map was
walking in DenseMap order. However, the keys to this map are
known---they're always the generic parameters of the requirement. So,
walk those generic parameters to make it deterministic, and don't
bother serializing them because they're known to the deserializer
already.

Fixes rdar://problem/29689811.
This commit is contained in:
Doug Gregor
2016-12-16 09:47:10 -08:00
parent 821965dee4
commit a9a8defe10
4 changed files with 53 additions and 55 deletions

View File

@@ -4318,15 +4318,19 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
// Generic signature and environment.
GenericSignature *syntheticSig = nullptr;
GenericEnvironment *syntheticEnv = nullptr;
// Requirement -> synthetic map.
SubstitutionMap reqToSyntheticMap;
bool hasReqToSyntheticMap = false;
if (unsigned numGenericParams = *rawIDIter++) {
// Generic parameters.
// Generic parameters of the synthetic environment.
SmallVector<GenericTypeParamType *, 2> genericParams;
while (numGenericParams--) {
genericParams.push_back(
getType(*rawIDIter++)->castTo<GenericTypeParamType>());
}
// Generic requirements.
// Generic requirements of the synthetic environment.
SmallVector<Requirement, 4> requirements;
readGenericRequirements(requirements, DeclTypeCursor);
@@ -4339,24 +4343,23 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
builder.addGenericSignature(syntheticSig);
builder.finalize(SourceLoc());
syntheticEnv = builder.getGenericEnvironment(syntheticSig);
}
// Requirement -> synthetic map.
SubstitutionMap reqToSyntheticMap;
bool hasReqToSyntheticMap = false;
if (unsigned numEntries = *rawIDIter++) {
// Requirement -> synthetic map.
hasReqToSyntheticMap = true;
while (numEntries--) {
auto first = getType(*rawIDIter++);
auto second = getType(*rawIDIter++);
reqToSyntheticMap.addSubstitution(first->getCanonicalType(), second);
auto reqSignature =
req->getInnermostDeclContext()->getGenericSignatureOfContext();
for (auto reqGP : reqSignature->getGenericParams()) {
auto canonicalGP =
cast<GenericTypeParamType>(reqGP->getCanonicalType());
auto concreteTy = getType(*rawIDIter++);
reqToSyntheticMap.addSubstitution(canonicalGP, concreteTy);
if (unsigned numConformances = *rawIDIter++) {
SmallVector<ProtocolConformanceRef, 2> conformances;
while (numConformances--) {
conformances.push_back(readConformance(DeclTypeCursor));
}
reqToSyntheticMap.addConformances(first->getCanonicalType(),
reqToSyntheticMap.addConformances(canonicalGP,
ctx.AllocateCopy(conformances));
}
}