Skip to content

Commit 7802d17

Browse files
authored
Merge pull request swiftlang#29639 from xymus/recover-in-getAllWitnessTables
[Serialization] Recover from a missing conforming type in a protocol conformance
2 parents 83668f9 + 6dc9dce commit 7802d17

File tree

7 files changed

+68
-7
lines changed

7 files changed

+68
-7
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,

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,10 @@ void swift::serialization::diagnoseSerializedASTLoadFailure(
738738
std::copy_if(
739739
loadedModuleFile->getDependencies().begin(),
740740
loadedModuleFile->getDependencies().end(), std::back_inserter(missing),
741-
[&duplicates](const ModuleFile::Dependency &dependency) -> bool {
741+
[&duplicates, &Ctx](const ModuleFile::Dependency &dependency) -> bool {
742742
if (dependency.isLoaded() || dependency.isHeader() ||
743-
dependency.isImplementationOnly()) {
743+
(dependency.isImplementationOnly() &&
744+
Ctx.LangOpts.DebuggerSupport)) {
744745
return false;
745746
}
746747
return duplicates.insert(dependency.RawPath).second;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
enum __attribute__((flag_enum,enum_extensibility(open))) CEnum : int {
2+
A = 1 << 0,
3+
B = 1 << 1,
4+
};

test/Serialization/Recovery/Inputs/custom-modules/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ module SuperclassObjC { header "SuperclassObjC.h" }
1313
module Typedefs { header "Typedefs.h" }
1414
module TypeRemovalObjC { header "TypeRemovalObjC.h" }
1515
module Types { header "Types.h" }
16+
module Conformance { header "Conformance.h" }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// Recover from reading witness table involving a synthesized conformance
2+
/// rdar://problem/58924131
3+
4+
// RUN: %empty-directory(%t)
5+
// RUN: cp -r %S/Inputs/custom-modules %t/
6+
// RUN: %target-swift-frontend -emit-module %s -module-name MyModule -emit-module-path %t/MyModule.swiftmodule -I %t/custom-modules -swift-version 5
7+
8+
/// Delete the clang module
9+
// RUN: rm -r %t/custom-modules/
10+
11+
// RUN: not %target-sil-opt %t/MyModule.swiftmodule 2>&1 | %FileCheck %s
12+
13+
@_implementationOnly import Conformance
14+
// CHECK: missing required module 'Conformance'
15+
16+
public func foo<T: OptionSet>(_ t: T) {}
17+
18+
foo(CEnum.A)

0 commit comments

Comments
 (0)