Skip to content

Commit 978ed67

Browse files
committed
[Serialization] Recover from a missing conforming type in a protocol conformance
We saw this failure with a Clang module imported @_implementationOnly with synthesized conformances by the ClangImporter. It caused issues only in sil-opt as it reads all the witness tables. rdar://problem/58924131 rdar://problem/61209195
1 parent b4a65a4 commit 978ed67

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,11 @@ ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
562562
ProtocolConformanceXrefLayout::readRecord(scratch, protoID, nominalID,
563563
moduleID);
564564

565-
auto nominal = cast<NominalTypeDecl>(getDecl(nominalID));
565+
auto maybeNominal = getDeclChecked(nominalID);
566+
if (!maybeNominal)
567+
return maybeNominal.takeError();
568+
569+
auto nominal = cast<NominalTypeDecl>(maybeNominal.get());
566570
PrettyStackTraceDecl trace("cross-referencing conformance for", nominal);
567571
auto proto = cast<ProtocolDecl>(getDecl(protoID));
568572
PrettyStackTraceDecl traceTo("... to", proto);

lib/Serialization/DeserializeSIL.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3062,6 +3062,16 @@ void SILDeserializer::readWitnessTableEntries(
30623062

30633063
SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
30643064
SILWitnessTable *existingWt) {
3065+
auto deserialized = readWitnessTableChecked(WId, existingWt);
3066+
if (!deserialized) {
3067+
MF->fatal(deserialized.takeError());
3068+
}
3069+
return deserialized.get();
3070+
}
3071+
3072+
llvm::Expected<SILWitnessTable *>
3073+
SILDeserializer::readWitnessTableChecked(DeclID WId,
3074+
SILWitnessTable *existingWt) {
30653075
if (WId == 0)
30663076
return nullptr;
30673077
assert(WId <= WitnessTables.size() && "invalid WitnessTable ID");
@@ -3108,8 +3118,12 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
31083118
}
31093119

31103120
// Deserialize Conformance.
3121+
auto maybeConformance = MF->readConformanceChecked(SILCursor);
3122+
if (!maybeConformance)
3123+
return maybeConformance.takeError();
3124+
31113125
auto theConformance = cast<RootProtocolConformance>(
3112-
MF->readConformance(SILCursor).getConcrete());
3126+
maybeConformance.get().getConcrete());
31133127

31143128
PrettyStackTraceConformance trace(SILMod.getASTContext(),
31153129
"deserializing SIL witness table for",
@@ -3186,8 +3200,18 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
31863200
void SILDeserializer::getAllWitnessTables() {
31873201
if (!WitnessTableList)
31883202
return;
3189-
for (unsigned I = 0, E = WitnessTables.size(); I < E; I++)
3190-
readWitnessTable(I + 1, nullptr);
3203+
for (unsigned I = 0, E = WitnessTables.size(); I < E; I++) {
3204+
auto maybeTable = readWitnessTableChecked(I + 1, nullptr);
3205+
if (!maybeTable) {
3206+
if (maybeTable.errorIsA<XRefNonLoadedModuleError>()) {
3207+
// This is most likely caused by decls hidden by an implementation-only
3208+
// import, it is safe to ignore for this function's purpose.
3209+
consumeError(maybeTable.takeError());
3210+
} else {
3211+
MF->fatal(maybeTable.takeError());
3212+
}
3213+
}
3214+
}
31913215
}
31923216

31933217
SILWitnessTable *

lib/Serialization/DeserializeSIL.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,17 @@ namespace swift {
118118
SILVTable *readVTable(serialization::DeclID);
119119
SILGlobalVariable *getGlobalForReference(StringRef Name);
120120
SILGlobalVariable *readGlobalVar(StringRef Name);
121-
SILWitnessTable *readWitnessTable(serialization::DeclID,
121+
122+
/// Read and return the witness table identified with \p WId.
123+
SILWitnessTable *readWitnessTable(serialization::DeclID WId,
122124
SILWitnessTable *existingWt);
125+
126+
/// Read the witness table identified with \p WId, return the table or
127+
/// the first error if any.
128+
llvm::Expected<SILWitnessTable *>
129+
readWitnessTableChecked(serialization::DeclID WId,
130+
SILWitnessTable *existingWt);
131+
123132
void readWitnessTableEntries(
124133
llvm::BitstreamEntry &entry,
125134
std::vector<SILWitnessTable::Entry> &witnessEntries,

0 commit comments

Comments
 (0)