Skip to content

Commit 960408c

Browse files
authored
Merge pull request #30779 from xymus/recover-in-getAllWitnessTables-5.2
[5.2][Serialization] Recover from a missing conforming type in a protocol conformance
2 parents 2aede97 + f4efec8 commit 960408c

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
@@ -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,

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,9 +708,10 @@ void swift::serialization::diagnoseSerializedASTLoadFailure(
708708
std::copy_if(
709709
loadedModuleFile->getDependencies().begin(),
710710
loadedModuleFile->getDependencies().end(), std::back_inserter(missing),
711-
[&duplicates](const ModuleFile::Dependency &dependency) -> bool {
711+
[&duplicates, &Ctx](const ModuleFile::Dependency &dependency) -> bool {
712712
if (dependency.isLoaded() || dependency.isHeader() ||
713-
dependency.isImplementationOnly()) {
713+
(dependency.isImplementationOnly() &&
714+
Ctx.LangOpts.DebuggerSupport)) {
714715
return false;
715716
}
716717
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)