Skip to content

Commit f9d9dcf

Browse files
authored
Merge pull request #5589 from DougGregor/witness-serialization
[Serialization] (De-)serialize witnesses completely.
2 parents b2562da + b5511bd commit f9d9dcf

File tree

9 files changed

+240
-49
lines changed

9 files changed

+240
-49
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class SubstitutionMap {
5656
return subMap;
5757
}
5858

59+
/// Retrieve the conformances for the given type.
60+
ArrayRef<ProtocolConformanceRef> getConformances(CanType type) const;
61+
5962
void addSubstitution(CanType type, Type replacement);
6063

6164
void addConformances(CanType type, ArrayRef<ProtocolConformanceRef> conformances);

include/swift/AST/Witness.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class ValueDecl;
8181
/// environment are those of the context of the protocol conformance (\c U
8282
/// and \c V, in the example above) and the innermost generic parameters are
8383
/// those of the generic requirement (\c T, in the example above). The
84-
/// \c Witness class contains this syntheetic environment (both its generic
84+
/// \c Witness class contains this synthetic environment (both its generic
8585
/// signature and a generic environment providing archetypes), a substitution
8686
/// map that allows one to map the interface types of the requirement into
8787
/// the interface types of the synthetic domain, and the set of substitutions

include/swift/Serialization/ModuleFile.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,14 @@ class ModuleFile : public LazyMemberLoader {
710710
/// Reads a substitution record from \c DeclTypeCursor.
711711
///
712712
/// If the record at the cursor is not a substitution, returns None.
713-
Optional<Substitution> maybeReadSubstitution(llvm::BitstreamCursor &Cursor);
713+
Optional<Substitution> maybeReadSubstitution(llvm::BitstreamCursor &Cursor,
714+
GenericEnvironment *genericEnv =
715+
nullptr);
714716

715717
/// Recursively reads a protocol conformance from the given cursor.
716-
ProtocolConformanceRef readConformance(llvm::BitstreamCursor &Cursor);
718+
ProtocolConformanceRef readConformance(llvm::BitstreamCursor &Cursor,
719+
GenericEnvironment *genericEnv =
720+
nullptr);
717721

718722
/// Read the given normal conformance from the current module file.
719723
NormalProtocolConformance *

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 280; // Last change: function qualified ownership
57+
const uint16_t VERSION_MINOR = 281; // Last change: complete witnesses
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ struct ASTNodeBase {};
18931893
}
18941894

18951895
// Check the witness substitutions.
1896-
auto witness = normal->getWitness(req, nullptr);
1896+
const auto &witness = normal->getWitness(req, nullptr);
18971897

18981898
if (witness.requiresSubstitution()) {
18991899
GenericEnv.push_back(witness.getSyntheticEnvironment());

lib/AST/SubstitutionMap.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ addConformances(CanType type, ArrayRef<ProtocolConformanceRef> conformances) {
106106
(void) result;
107107
}
108108

109+
ArrayRef<ProtocolConformanceRef> SubstitutionMap::
110+
getConformances(CanType type) const {
111+
auto known = conformanceMap.find(type.getPointer());
112+
if (known == conformanceMap.end()) return { };
113+
return known->second;
114+
}
115+
109116
void SubstitutionMap::
110117
addParent(CanType type, CanType parent, AssociatedTypeDecl *assocType) {
111118
assert(type && parent && assocType);

lib/Serialization/Deserialization.cpp

Lines changed: 103 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,9 @@ Pattern *ModuleFile::maybeReadPattern() {
450450
}
451451
}
452452

453-
ProtocolConformanceRef ModuleFile::readConformance(llvm::BitstreamCursor &Cursor){
453+
ProtocolConformanceRef ModuleFile::readConformance(
454+
llvm::BitstreamCursor &Cursor,
455+
GenericEnvironment *genericEnv) {
454456
using namespace decls_block;
455457

456458
SmallVector<uint64_t, 16> scratch;
@@ -475,6 +477,10 @@ ProtocolConformanceRef ModuleFile::readConformance(llvm::BitstreamCursor &Cursor
475477

476478
ASTContext &ctx = getContext();
477479
Type conformingType = getType(conformingTypeID);
480+
if (genericEnv) {
481+
conformingType = genericEnv->mapTypeIntoContext(getAssociatedModule(),
482+
conformingType);
483+
}
478484

479485
PrettyStackTraceType trace(getAssociatedModule()->getASTContext(),
480486
"reading specialized conformance for",
@@ -483,12 +489,13 @@ ProtocolConformanceRef ModuleFile::readConformance(llvm::BitstreamCursor &Cursor
483489
// Read the substitutions.
484490
SmallVector<Substitution, 4> substitutions;
485491
while (numSubstitutions--) {
486-
auto sub = maybeReadSubstitution(Cursor);
492+
auto sub = maybeReadSubstitution(Cursor, genericEnv);
487493
assert(sub.hasValue() && "Missing substitution?");
488494
substitutions.push_back(*sub);
489495
}
490496

491-
ProtocolConformanceRef genericConformance = readConformance(Cursor);
497+
ProtocolConformanceRef genericConformance =
498+
readConformance(Cursor, genericEnv);
492499
PrettyStackTraceDecl traceTo("... to", genericConformance.getRequirement());
493500

494501
assert(genericConformance.isConcrete() && "Abstract generic conformance?");
@@ -505,11 +512,17 @@ ProtocolConformanceRef ModuleFile::readConformance(llvm::BitstreamCursor &Cursor
505512

506513
ASTContext &ctx = getContext();
507514
Type conformingType = getType(conformingTypeID);
515+
if (genericEnv) {
516+
conformingType = genericEnv->mapTypeIntoContext(getAssociatedModule(),
517+
conformingType);
518+
}
519+
508520
PrettyStackTraceType trace(getAssociatedModule()->getASTContext(),
509521
"reading inherited conformance for",
510522
conformingType);
511523

512-
ProtocolConformanceRef inheritedConformance = readConformance(Cursor);
524+
ProtocolConformanceRef inheritedConformance =
525+
readConformance(Cursor, genericEnv);
513526
PrettyStackTraceDecl traceTo("... to",
514527
inheritedConformance.getRequirement());
515528

@@ -541,8 +554,7 @@ ProtocolConformanceRef ModuleFile::readConformance(llvm::BitstreamCursor &Cursor
541554
auto module = getModule(moduleID);
542555

543556
SmallVector<ProtocolConformance *, 2> conformances;
544-
nominal->lookupConformance(module, proto,
545-
conformances);
557+
nominal->lookupConformance(module, proto, conformances);
546558
PrettyStackTraceModuleFile traceMsg(
547559
"If you're seeing a crash here, check that your SDK and dependencies "
548560
"are at least as new as the versions used to build", this);
@@ -641,7 +653,8 @@ NormalProtocolConformance *ModuleFile::readNormalConformance(
641653
}
642654

643655
Optional<Substitution>
644-
ModuleFile::maybeReadSubstitution(llvm::BitstreamCursor &cursor) {
656+
ModuleFile::maybeReadSubstitution(llvm::BitstreamCursor &cursor,
657+
GenericEnvironment *genericEnv) {
645658
BCOffsetRAII lastRecordOffset(cursor);
646659

647660
auto entry = cursor.advance(AF_DontPopBlockAtEnd);
@@ -661,6 +674,10 @@ ModuleFile::maybeReadSubstitution(llvm::BitstreamCursor &cursor) {
661674
numConformances);
662675

663676
auto replacementTy = getType(replacementID);
677+
if (genericEnv) {
678+
replacementTy = genericEnv->mapTypeIntoContext(getAssociatedModule(),
679+
replacementTy);
680+
}
664681

665682
SmallVector<ProtocolConformanceRef, 4> conformanceBuf;
666683
while (numConformances--) {
@@ -4206,17 +4223,85 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
42064223
ASTContext &ctx = getContext();
42074224
ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();
42084225

4209-
WitnessMap witnesses;
42104226
while (valueCount--) {
4211-
auto first = cast<ValueDecl>(getDecl(*rawIDIter++));
4212-
auto second = cast_or_null<ValueDecl>(getDecl(*rawIDIter++));
4213-
assert(second || first->getAttrs().hasAttribute<OptionalAttr>() ||
4214-
first->getAttrs().isUnavailable(ctx));
4215-
(void) ctx;
4216-
if (second)
4217-
witnesses.insert(std::make_pair(first, second));
4218-
else
4219-
witnesses.insert(std::make_pair(first, Witness()));
4227+
auto req = cast<ValueDecl>(getDecl(*rawIDIter++));
4228+
auto witness = cast_or_null<ValueDecl>(getDecl(*rawIDIter++));
4229+
assert(witness ||
4230+
req->getAttrs().hasAttribute<OptionalAttr>() ||
4231+
req->getAttrs().isUnavailable(ctx));
4232+
if (!witness) {
4233+
conformance->setWitness(req, Witness());
4234+
continue;
4235+
}
4236+
4237+
// Generic signature and environment.
4238+
GenericSignature *syntheticSig = nullptr;
4239+
GenericEnvironment *syntheticEnv = nullptr;
4240+
if (unsigned numGenericParams = *rawIDIter++) {
4241+
// Generic parameters.
4242+
SmallVector<GenericTypeParamType *, 2> genericParams;
4243+
while (numGenericParams--) {
4244+
genericParams.push_back(
4245+
getType(*rawIDIter++)->castTo<GenericTypeParamType>());
4246+
}
4247+
4248+
// Generic requirements.
4249+
SmallVector<Requirement, 4> requirements;
4250+
readGenericRequirements(requirements);
4251+
4252+
// Form the generic signature for the synthetic environment.
4253+
syntheticSig = GenericSignature::get(genericParams, requirements);
4254+
4255+
// Create an archetype builder, which will help us create the
4256+
// synthetic environment.
4257+
ArchetypeBuilder builder(*getAssociatedModule(), ctx.Diags);
4258+
builder.addGenericSignature(syntheticSig, nullptr);
4259+
builder.finalize(SourceLoc());
4260+
syntheticEnv = builder.getGenericEnvironment();
4261+
}
4262+
4263+
// Requirement -> synthetic map.
4264+
SubstitutionMap reqToSyntheticMap;
4265+
bool hasReqToSyntheticMap = false;
4266+
if (unsigned numEntries = *rawIDIter++) {
4267+
hasReqToSyntheticMap = true;
4268+
while (numEntries--) {
4269+
auto first = getType(*rawIDIter++);
4270+
auto second = getType(*rawIDIter++);
4271+
reqToSyntheticMap.addSubstitution(first->getCanonicalType(), second);
4272+
4273+
if (unsigned numConformances = *rawIDIter++) {
4274+
SmallVector<ProtocolConformanceRef, 2> conformances;
4275+
while (numConformances--) {
4276+
conformances.push_back(readConformance(DeclTypeCursor));
4277+
}
4278+
reqToSyntheticMap.addConformances(first->getCanonicalType(),
4279+
ctx.AllocateCopy(conformances));
4280+
}
4281+
}
4282+
}
4283+
4284+
// Witness substitutions.
4285+
SmallVector<Substitution, 4> witnessSubstitutions;
4286+
if (unsigned numWitnessSubstitutions = *rawIDIter++) {
4287+
while (numWitnessSubstitutions--) {
4288+
auto sub = maybeReadSubstitution(DeclTypeCursor, syntheticEnv);
4289+
witnessSubstitutions.push_back(*sub);
4290+
}
4291+
}
4292+
4293+
// Handle simple witnesses.
4294+
if (witnessSubstitutions.empty() && !syntheticSig && !syntheticEnv &&
4295+
!hasReqToSyntheticMap) {
4296+
conformance->setWitness(req, Witness(witness));
4297+
continue;
4298+
}
4299+
4300+
// Set the witness.
4301+
conformance->setWitness(req,
4302+
Witness(witness, witnessSubstitutions,
4303+
syntheticSig, syntheticEnv,
4304+
reqToSyntheticMap));
42204305
}
42214306
assert(rawIDIter <= rawIDs.end() && "read too much");
42224307

@@ -4232,16 +4317,12 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
42324317
}
42334318
assert(rawIDIter <= rawIDs.end() && "read too much");
42344319

4320+
42354321
// Set type witnesses.
42364322
for (auto typeWitness : typeWitnesses) {
42374323
conformance->setTypeWitness(typeWitness.first, typeWitness.second.first,
42384324
typeWitness.second.second);
42394325
}
4240-
4241-
// Set witnesses.
4242-
for (auto witness : witnesses) {
4243-
conformance->setWitness(witness.first, witness.second);
4244-
}
42454326
}
42464327

42474328
static Optional<ForeignErrorConvention::Kind>

0 commit comments

Comments
 (0)