@@ -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 *>
@@ -7867,7 +7892,7 @@ Expected<Type> DESERIALIZE_TYPE(SIL_FUNCTION_TYPE)(
78677892 ProtocolConformanceRef witnessMethodConformance;
78687893 if (*representation == swift::SILFunctionTypeRepresentation::WitnessMethod) {
78697894 auto conformanceID = variableData[nextVariableDataIndex++];
7870- witnessMethodConformance = MF.getConformance (conformanceID);
7895+ UNWRAP ( MF.getConformanceChecked (conformanceID), witnessMethodConformance );
78717896 }
78727897
78737898 GenericSignature invocationSig =
@@ -8647,21 +8672,37 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
86478672 scratch, protoID, contextID, typeCount, valueCount, conformanceCount,
86488673 rawOptions, rawIDs);
86498674
8675+ const ProtocolDecl *proto = conformance->getProtocol ();
8676+
86508677 // Read requirement signature conformances.
86518678 SmallVector<ProtocolConformanceRef, 4 > reqConformances;
86528679 for (auto conformanceID : rawIDs.slice (0 , conformanceCount)) {
86538680 auto maybeConformance = getConformanceChecked (conformanceID);
86548681 if (maybeConformance) {
86558682 reqConformances.push_back (maybeConformance.get ());
86568683 } else if (getContext ().LangOpts .EnableDeserializationRecovery ) {
8657- diagnoseAndConsumeError (maybeConformance.takeError ());
8684+ llvm::Error error = maybeConformance.takeError ();
8685+ if (error.isA <ConformanceXRefError>() &&
8686+ !enableExtendedDeserializationRecovery ()) {
8687+
8688+ std::string typeStr = conformance->getType ()->getString ();
8689+ auto &diags = getContext ().Diags ;
8690+ diags.diagnose (getSourceLoc (),
8691+ diag::modularization_issue_conformance_xref_note,
8692+ typeStr, proto->getName ());
8693+
8694+ consumeError (std::move (error));
8695+ conformance->setInvalid ();
8696+ return ;
8697+ }
8698+
8699+ diagnoseAndConsumeError (std::move (error));
86588700 reqConformances.push_back (ProtocolConformanceRef::forInvalid ());
86598701 } else {
86608702 fatal (maybeConformance.takeError ());
86618703 }
86628704 }
86638705
8664- const ProtocolDecl *proto = conformance->getProtocol ();
86658706 if (proto->isObjC () && getContext ().LangOpts .EnableDeserializationRecovery ) {
86668707 // Don't crash if inherited protocols are added or removed.
86678708 // This is limited to Objective-C protocols because we know their only
@@ -8702,12 +8743,39 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
87028743 return req.getKind () == RequirementKind::Conformance;
87038744 };
87048745 auto requirements = proto->getRequirementSignature ().getRequirements ();
8705- if (!allowCompilerErrors () &&
8706- conformanceCount != llvm::count_if (requirements,
8707- isConformanceReq)) {
8708- fatal (llvm::make_error<llvm::StringError>(
8709- " serialized conformances do not match requirement signature" ,
8710- llvm::inconvertibleErrorCode ()));
8746+ unsigned int conformanceRequirementCount =
8747+ llvm::count_if (requirements, isConformanceReq);
8748+ if (conformanceCount != conformanceRequirementCount) {
8749+ // Mismatch between the number of loaded conformances and the expected
8750+ // requirements. One or the other likely comes from a stale module.
8751+
8752+ if (!enableExtendedDeserializationRecovery ()) {
8753+ // Error and print full context for visual inspection.
8754+ ASTContext &ctx = getContext ();
8755+ std::string typeStr = conformance->getType ()->getString ();
8756+ ctx.Diags .diagnose (getSourceLoc (),
8757+ diag::modularization_issue_conformance_error,
8758+ typeStr, proto->getName (), conformanceCount,
8759+ conformanceRequirementCount);
8760+ ctx.Diags .flushConsumers ();
8761+
8762+ // Print context to stderr.
8763+ PrintOptions Opts;
8764+ llvm::errs () << " Requirements:\n " ;
8765+ for (auto req: requirements) {
8766+ req.print (llvm::errs (), Opts);
8767+ llvm::errs () << " \n " ;
8768+ }
8769+
8770+ llvm::errs () << " Conformances:\n " ;
8771+ for (auto req: reqConformances) {
8772+ req.print (llvm::errs ());
8773+ llvm::errs () << " \n " ;
8774+ }
8775+ }
8776+
8777+ conformance->setInvalid ();
8778+ return ;
87118779 }
87128780 }
87138781
0 commit comments