diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 82c682f4cb33e..43ad180497b2a 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -562,7 +562,11 @@ ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor, ProtocolConformanceXrefLayout::readRecord(scratch, protoID, nominalID, moduleID); - auto nominal = cast(getDecl(nominalID)); + auto maybeNominal = getDeclChecked(nominalID); + if (!maybeNominal) + return maybeNominal.takeError(); + + auto nominal = cast(maybeNominal.get()); PrettyStackTraceDecl trace("cross-referencing conformance for", nominal); auto proto = cast(getDecl(protoID)); PrettyStackTraceDecl traceTo("... to", proto); diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index eb97ef6d9c322..a35d19be0d96b 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -3062,6 +3062,16 @@ void SILDeserializer::readWitnessTableEntries( SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId, SILWitnessTable *existingWt) { + auto deserialized = readWitnessTableChecked(WId, existingWt); + if (!deserialized) { + MF->fatal(deserialized.takeError()); + } + return deserialized.get(); +} + +llvm::Expected + SILDeserializer::readWitnessTableChecked(DeclID WId, + SILWitnessTable *existingWt) { if (WId == 0) return nullptr; assert(WId <= WitnessTables.size() && "invalid WitnessTable ID"); @@ -3108,8 +3118,12 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId, } // Deserialize Conformance. + auto maybeConformance = MF->readConformanceChecked(SILCursor); + if (!maybeConformance) + return maybeConformance.takeError(); + auto theConformance = cast( - MF->readConformance(SILCursor).getConcrete()); + maybeConformance.get().getConcrete()); PrettyStackTraceConformance trace(SILMod.getASTContext(), "deserializing SIL witness table for", @@ -3186,8 +3200,18 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId, void SILDeserializer::getAllWitnessTables() { if (!WitnessTableList) return; - for (unsigned I = 0, E = WitnessTables.size(); I < E; I++) - readWitnessTable(I + 1, nullptr); + for (unsigned I = 0, E = WitnessTables.size(); I < E; I++) { + auto maybeTable = readWitnessTableChecked(I + 1, nullptr); + if (!maybeTable) { + if (maybeTable.errorIsA()) { + // This is most likely caused by decls hidden by an implementation-only + // import, it is safe to ignore for this function's purpose. + consumeError(maybeTable.takeError()); + } else { + MF->fatal(maybeTable.takeError()); + } + } + } } SILWitnessTable * diff --git a/lib/Serialization/DeserializeSIL.h b/lib/Serialization/DeserializeSIL.h index 24147978b6bba..14d318c932c40 100644 --- a/lib/Serialization/DeserializeSIL.h +++ b/lib/Serialization/DeserializeSIL.h @@ -118,8 +118,17 @@ namespace swift { SILVTable *readVTable(serialization::DeclID); SILGlobalVariable *getGlobalForReference(StringRef Name); SILGlobalVariable *readGlobalVar(StringRef Name); - SILWitnessTable *readWitnessTable(serialization::DeclID, + + /// Read and return the witness table identified with \p WId. + SILWitnessTable *readWitnessTable(serialization::DeclID WId, SILWitnessTable *existingWt); + + /// Read the witness table identified with \p WId, return the table or + /// the first error if any. + llvm::Expected + readWitnessTableChecked(serialization::DeclID WId, + SILWitnessTable *existingWt); + void readWitnessTableEntries( llvm::BitstreamEntry &entry, std::vector &witnessEntries, diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 903391055dd75..4f09bf47763cb 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -708,9 +708,10 @@ void swift::serialization::diagnoseSerializedASTLoadFailure( std::copy_if( loadedModuleFile->getDependencies().begin(), loadedModuleFile->getDependencies().end(), std::back_inserter(missing), - [&duplicates](const ModuleFile::Dependency &dependency) -> bool { + [&duplicates, &Ctx](const ModuleFile::Dependency &dependency) -> bool { if (dependency.isLoaded() || dependency.isHeader() || - dependency.isImplementationOnly()) { + (dependency.isImplementationOnly() && + Ctx.LangOpts.DebuggerSupport)) { return false; } return duplicates.insert(dependency.RawPath).second; diff --git a/test/Serialization/Recovery/Inputs/custom-modules/Conformance.h b/test/Serialization/Recovery/Inputs/custom-modules/Conformance.h new file mode 100644 index 0000000000000..4c998fbffeeac --- /dev/null +++ b/test/Serialization/Recovery/Inputs/custom-modules/Conformance.h @@ -0,0 +1,4 @@ +enum __attribute__((flag_enum,enum_extensibility(open))) CEnum : int { + A = 1 << 0, + B = 1 << 1, +}; diff --git a/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap b/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap index 203ab78816cd6..89ef36dd3b5d8 100644 --- a/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap +++ b/test/Serialization/Recovery/Inputs/custom-modules/module.modulemap @@ -13,3 +13,4 @@ module SuperclassObjC { header "SuperclassObjC.h" } module Typedefs { header "Typedefs.h" } module TypeRemovalObjC { header "TypeRemovalObjC.h" } module Types { header "Types.h" } +module Conformance { header "Conformance.h" } diff --git a/test/Serialization/Recovery/missing-clang-module-conformance.swift b/test/Serialization/Recovery/missing-clang-module-conformance.swift new file mode 100644 index 0000000000000..5ca344d7b2706 --- /dev/null +++ b/test/Serialization/Recovery/missing-clang-module-conformance.swift @@ -0,0 +1,18 @@ +/// Recover from reading witness table involving a synthesized conformance +/// rdar://problem/58924131 + +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/custom-modules %t/ +// RUN: %target-swift-frontend -emit-module %s -module-name MyModule -emit-module-path %t/MyModule.swiftmodule -I %t/custom-modules -swift-version 5 + +/// Delete the clang module +// RUN: rm -r %t/custom-modules/ + +// RUN: not %target-sil-opt %t/MyModule.swiftmodule 2>&1 | %FileCheck %s + +@_implementationOnly import Conformance +// CHECK: missing required module 'Conformance' + +public func foo(_ t: T) {} + +foo(CEnum.A)