Skip to content

Commit 07ade1d

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
1 parent b0b927b commit 07ade1d

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
@@ -581,7 +581,11 @@ ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
581581
ProtocolConformanceXrefLayout::readRecord(scratch, protoID, nominalID,
582582
moduleID);
583583

584-
auto nominal = cast<NominalTypeDecl>(getDecl(nominalID));
584+
auto maybeNominal = getDeclChecked(nominalID);
585+
if (!maybeNominal)
586+
return maybeNominal.takeError();
587+
588+
auto nominal = cast<NominalTypeDecl>(maybeNominal.get());
585589
PrettyStackTraceDecl trace("cross-referencing conformance for", nominal);
586590
auto proto = cast<ProtocolDecl>(getDecl(protoID));
587591
PrettyStackTraceDecl traceTo("... to", proto);

lib/Serialization/DeserializeSIL.cpp

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

31053105
SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
31063106
SILWitnessTable *existingWt) {
3107+
auto deserialized = readWitnessTableChecked(WId, existingWt);
3108+
if (!deserialized) {
3109+
MF->fatal(deserialized.takeError());
3110+
}
3111+
return deserialized.get();
3112+
}
3113+
3114+
llvm::Expected<SILWitnessTable *>
3115+
SILDeserializer::readWitnessTableChecked(DeclID WId,
3116+
SILWitnessTable *existingWt) {
31073117
if (WId == 0)
31083118
return nullptr;
31093119
assert(WId <= WitnessTables.size() && "invalid WitnessTable ID");
@@ -3150,8 +3160,12 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
31503160
}
31513161

31523162
// Deserialize Conformance.
3163+
auto maybeConformance = MF->readConformanceChecked(SILCursor);
3164+
if (!maybeConformance)
3165+
return maybeConformance.takeError();
3166+
31533167
auto theConformance = cast<RootProtocolConformance>(
3154-
MF->readConformance(SILCursor).getConcrete());
3168+
maybeConformance.get().getConcrete());
31553169

31563170
PrettyStackTraceConformance trace(SILMod.getASTContext(),
31573171
"deserializing SIL witness table for",
@@ -3228,8 +3242,18 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
32283242
void SILDeserializer::getAllWitnessTables() {
32293243
if (!WitnessTableList)
32303244
return;
3231-
for (unsigned I = 0, E = WitnessTables.size(); I < E; I++)
3232-
readWitnessTable(I + 1, nullptr);
3245+
for (unsigned I = 0, E = WitnessTables.size(); I < E; I++) {
3246+
auto maybeTable = readWitnessTableChecked(I + 1, nullptr);
3247+
if (!maybeTable) {
3248+
if (maybeTable.errorIsA<XRefNonLoadedModuleError>()) {
3249+
// This is most likely caused by decls hidden by an implementation-only
3250+
// import, it is safe to ignore for this function's purpose.
3251+
consumeError(maybeTable.takeError());
3252+
} else {
3253+
MF->fatal(maybeTable.takeError());
3254+
}
3255+
}
3256+
}
32333257
}
32343258

32353259
SILWitnessTable *

lib/Serialization/DeserializeSIL.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,17 @@ namespace swift {
126126
SILVTable *readVTable(serialization::DeclID);
127127
SILGlobalVariable *getGlobalForReference(StringRef Name);
128128
SILGlobalVariable *readGlobalVar(StringRef Name);
129-
SILWitnessTable *readWitnessTable(serialization::DeclID,
129+
130+
/// Read and return the witness table identified with \p WId.
131+
SILWitnessTable *readWitnessTable(serialization::DeclID WId,
130132
SILWitnessTable *existingWt);
133+
134+
/// Read the witness table identified with \p WId, return the table or
135+
/// the first error if any.
136+
llvm::Expected<SILWitnessTable *>
137+
readWitnessTableChecked(serialization::DeclID WId,
138+
SILWitnessTable *existingWt);
139+
131140
void readWitnessTableEntries(
132141
llvm::BitstreamEntry &entry,
133142
std::vector<SILWitnessTable::Entry> &witnessEntries,

0 commit comments

Comments
 (0)