@@ -179,6 +179,8 @@ const char ModularizationError::ID = '\0';
179179void ModularizationError::anchor () {}
180180const char InvalidEnumValueError::ID = ' \0 ' ;
181181void InvalidEnumValueError::anchor () {}
182+ const char ConformanceXRefError::ID = ' \0 ' ;
183+ void ConformanceXRefError::anchor () {}
182184
183185// / Skips a single record in the bitstream.
184186// /
@@ -404,6 +406,16 @@ ModuleFile::diagnoseModularizationError(llvm::Error error,
404406 return outError;
405407}
406408
409+ void
410+ ConformanceXRefError::diagnose (const ModuleFile *MF,
411+ DiagnosticBehavior limit) const {
412+ auto &diags = MF->getContext ().Diags ;
413+ diags.diagnose (MF->getSourceLoc (),
414+ diag::modularization_issue_conformance_xref_error,
415+ name, protoName, expectedModule->getName ())
416+ .limitBehavior (limit);
417+ }
418+
407419llvm::Error ModuleFile::diagnoseFatal (llvm::Error error) const {
408420
409421 auto &ctx = getContext ();
@@ -860,7 +872,8 @@ ProtocolConformanceDeserializer::readSpecializedProtocolConformance(
860872 return subMapOrError.takeError ();
861873 auto subMap = subMapOrError.get ();
862874
863- auto genericConformance = MF.getConformance (conformanceID);
875+ ProtocolConformanceRef genericConformance;
876+ UNWRAP (MF.getConformanceChecked (conformanceID), genericConformance);
864877
865878 PrettyStackTraceDecl traceTo (" ... to" , genericConformance.getRequirement ());
866879 ++NumNormalProtocolConformancesLoaded;
@@ -892,8 +905,8 @@ ProtocolConformanceDeserializer::readInheritedProtocolConformance(
892905 PrettyStackTraceType trace (ctx, " reading inherited conformance for" ,
893906 conformingType);
894907
895- ProtocolConformanceRef inheritedConformance =
896- MF.getConformance (conformanceID);
908+ ProtocolConformanceRef inheritedConformance;
909+ UNWRAP ( MF.getConformanceChecked (conformanceID), inheritedConformance );
897910 PrettyStackTraceDecl traceTo (" ... to" ,
898911 inheritedConformance.getRequirement ());
899912
@@ -943,14 +956,16 @@ ProtocolConformanceDeserializer::readNormalProtocolConformanceXRef(
943956 ProtocolConformanceXrefLayout::readRecord (scratch, protoID, nominalID,
944957 moduleID);
945958
946- auto maybeNominal = MF.getDeclChecked (nominalID);
947- if (!maybeNominal)
948- return maybeNominal.takeError ();
949-
950- auto nominal = cast<NominalTypeDecl>(maybeNominal.get ());
959+ Decl *maybeNominal;
960+ UNWRAP (MF.getDeclChecked (nominalID), maybeNominal);
961+ auto nominal = cast<NominalTypeDecl>(maybeNominal);
951962 PrettyStackTraceDecl trace (" cross-referencing conformance for" , nominal);
952- auto proto = cast<ProtocolDecl>(MF.getDecl (protoID));
963+
964+ Decl *maybeProto;
965+ UNWRAP (MF.getDeclChecked (protoID), maybeProto);
966+ auto proto = cast<ProtocolDecl>(maybeProto);
953967 PrettyStackTraceDecl traceTo (" ... to" , proto);
968+
954969 auto module = MF.getModule (moduleID);
955970
956971 // FIXME: If the module hasn't been loaded, we probably don't want to fall
@@ -971,16 +986,26 @@ ProtocolConformanceDeserializer::readNormalProtocolConformanceXRef(
971986 // TODO: Sink Sendable derivation into the conformance lookup table
972987 if (proto->isSpecificProtocol (KnownProtocolKind::Sendable)) {
973988 auto conformanceRef = lookupConformance (nominal->getDeclaredInterfaceType (), proto);
974- if (!conformanceRef.isConcrete ())
975- abort ();
976- return conformanceRef.getConcrete ();
989+ if (conformanceRef.isConcrete ())
990+ return conformanceRef.getConcrete ();
977991 } else {
978992 SmallVector<ProtocolConformance *, 2 > conformances;
979993 nominal->lookupConformance (proto, conformances);
980- if (conformances.empty ())
981- abort ();
982- return conformances.front ();
994+ if (!conformances.empty ())
995+ return conformances.front ();
983996 }
997+
998+ auto error = llvm::make_error<ConformanceXRefError>(
999+ nominal->getName (), proto->getName (), module );
1000+
1001+ if (!MF.enableExtendedDeserializationRecovery ()) {
1002+ error = llvm::handleErrors (std::move (error),
1003+ [&](const ConformanceXRefError &error) -> llvm::Error {
1004+ error.diagnose (&MF);
1005+ return llvm::make_error<ConformanceXRefError>(std::move (error));
1006+ });
1007+ }
1008+ return error;
9841009}
9851010
9861011Expected<ProtocolConformance *>
@@ -7863,7 +7888,7 @@ Expected<Type> DESERIALIZE_TYPE(SIL_FUNCTION_TYPE)(
78637888 ProtocolConformanceRef witnessMethodConformance;
78647889 if (*representation == swift::SILFunctionTypeRepresentation::WitnessMethod) {
78657890 auto conformanceID = variableData[nextVariableDataIndex++];
7866- witnessMethodConformance = MF.getConformance (conformanceID);
7891+ UNWRAP ( MF.getConformanceChecked (conformanceID), witnessMethodConformance );
78677892 }
78687893
78697894 GenericSignature invocationSig =
@@ -8643,21 +8668,37 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
86438668 scratch, protoID, contextID, typeCount, valueCount, conformanceCount,
86448669 rawOptions, rawIDs);
86458670
8671+ const ProtocolDecl *proto = conformance->getProtocol ();
8672+
86468673 // Read requirement signature conformances.
86478674 SmallVector<ProtocolConformanceRef, 4 > reqConformances;
86488675 for (auto conformanceID : rawIDs.slice (0 , conformanceCount)) {
86498676 auto maybeConformance = getConformanceChecked (conformanceID);
86508677 if (maybeConformance) {
86518678 reqConformances.push_back (maybeConformance.get ());
86528679 } else if (getContext ().LangOpts .EnableDeserializationRecovery ) {
8653- diagnoseAndConsumeError (maybeConformance.takeError ());
8680+ llvm::Error error = maybeConformance.takeError ();
8681+ if (error.isA <ConformanceXRefError>() &&
8682+ !enableExtendedDeserializationRecovery ()) {
8683+
8684+ std::string typeStr = conformance->getType ()->getString ();
8685+ auto &diags = getContext ().Diags ;
8686+ diags.diagnose (getSourceLoc (),
8687+ diag::modularization_issue_conformance_xref_note,
8688+ typeStr, proto->getName ());
8689+
8690+ consumeError (std::move (error));
8691+ conformance->setInvalid ();
8692+ return ;
8693+ }
8694+
8695+ diagnoseAndConsumeError (std::move (error));
86548696 reqConformances.push_back (ProtocolConformanceRef::forInvalid ());
86558697 } else {
86568698 fatal (maybeConformance.takeError ());
86578699 }
86588700 }
86598701
8660- const ProtocolDecl *proto = conformance->getProtocol ();
86618702 if (proto->isObjC () && getContext ().LangOpts .EnableDeserializationRecovery ) {
86628703 // Don't crash if inherited protocols are added or removed.
86638704 // This is limited to Objective-C protocols because we know their only
0 commit comments