@@ -179,6 +179,8 @@ const char ModularizationError::ID = '\0';
179
179
void ModularizationError::anchor () {}
180
180
const char InvalidEnumValueError::ID = ' \0 ' ;
181
181
void InvalidEnumValueError::anchor () {}
182
+ const char ConformanceXRefError::ID = ' \0 ' ;
183
+ void ConformanceXRefError::anchor () {}
182
184
183
185
// / Skips a single record in the bitstream.
184
186
// /
@@ -404,6 +406,16 @@ ModuleFile::diagnoseModularizationError(llvm::Error error,
404
406
return outError;
405
407
}
406
408
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
+
407
419
llvm::Error ModuleFile::diagnoseFatal (llvm::Error error) const {
408
420
409
421
auto &ctx = getContext ();
@@ -860,7 +872,8 @@ ProtocolConformanceDeserializer::readSpecializedProtocolConformance(
860
872
return subMapOrError.takeError ();
861
873
auto subMap = subMapOrError.get ();
862
874
863
- auto genericConformance = MF.getConformance (conformanceID);
875
+ ProtocolConformanceRef genericConformance;
876
+ UNWRAP (MF.getConformanceChecked (conformanceID), genericConformance);
864
877
865
878
PrettyStackTraceDecl traceTo (" ... to" , genericConformance.getRequirement ());
866
879
++NumNormalProtocolConformancesLoaded;
@@ -892,8 +905,8 @@ ProtocolConformanceDeserializer::readInheritedProtocolConformance(
892
905
PrettyStackTraceType trace (ctx, " reading inherited conformance for" ,
893
906
conformingType);
894
907
895
- ProtocolConformanceRef inheritedConformance =
896
- MF.getConformance (conformanceID);
908
+ ProtocolConformanceRef inheritedConformance;
909
+ UNWRAP ( MF.getConformanceChecked (conformanceID), inheritedConformance );
897
910
PrettyStackTraceDecl traceTo (" ... to" ,
898
911
inheritedConformance.getRequirement ());
899
912
@@ -943,14 +956,16 @@ ProtocolConformanceDeserializer::readNormalProtocolConformanceXRef(
943
956
ProtocolConformanceXrefLayout::readRecord (scratch, protoID, nominalID,
944
957
moduleID);
945
958
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);
951
962
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);
953
967
PrettyStackTraceDecl traceTo (" ... to" , proto);
968
+
954
969
auto module = MF.getModule (moduleID);
955
970
956
971
// FIXME: If the module hasn't been loaded, we probably don't want to fall
@@ -971,16 +986,26 @@ ProtocolConformanceDeserializer::readNormalProtocolConformanceXRef(
971
986
// TODO: Sink Sendable derivation into the conformance lookup table
972
987
if (proto->isSpecificProtocol (KnownProtocolKind::Sendable)) {
973
988
auto conformanceRef = lookupConformance (nominal->getDeclaredInterfaceType (), proto);
974
- if (!conformanceRef.isConcrete ())
975
- abort ();
976
- return conformanceRef.getConcrete ();
989
+ if (conformanceRef.isConcrete ())
990
+ return conformanceRef.getConcrete ();
977
991
} else {
978
992
SmallVector<ProtocolConformance *, 2 > conformances;
979
993
nominal->lookupConformance (proto, conformances);
980
- if (conformances.empty ())
981
- abort ();
982
- return conformances.front ();
994
+ if (!conformances.empty ())
995
+ return conformances.front ();
983
996
}
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;
984
1009
}
985
1010
986
1011
Expected<ProtocolConformance *>
@@ -7867,7 +7892,7 @@ Expected<Type> DESERIALIZE_TYPE(SIL_FUNCTION_TYPE)(
7867
7892
ProtocolConformanceRef witnessMethodConformance;
7868
7893
if (*representation == swift::SILFunctionTypeRepresentation::WitnessMethod) {
7869
7894
auto conformanceID = variableData[nextVariableDataIndex++];
7870
- witnessMethodConformance = MF.getConformance (conformanceID);
7895
+ UNWRAP ( MF.getConformanceChecked (conformanceID), witnessMethodConformance );
7871
7896
}
7872
7897
7873
7898
GenericSignature invocationSig =
@@ -8647,21 +8672,37 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
8647
8672
scratch, protoID, contextID, typeCount, valueCount, conformanceCount,
8648
8673
rawOptions, rawIDs);
8649
8674
8675
+ const ProtocolDecl *proto = conformance->getProtocol ();
8676
+
8650
8677
// Read requirement signature conformances.
8651
8678
SmallVector<ProtocolConformanceRef, 4 > reqConformances;
8652
8679
for (auto conformanceID : rawIDs.slice (0 , conformanceCount)) {
8653
8680
auto maybeConformance = getConformanceChecked (conformanceID);
8654
8681
if (maybeConformance) {
8655
8682
reqConformances.push_back (maybeConformance.get ());
8656
8683
} 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));
8658
8700
reqConformances.push_back (ProtocolConformanceRef::forInvalid ());
8659
8701
} else {
8660
8702
fatal (maybeConformance.takeError ());
8661
8703
}
8662
8704
}
8663
8705
8664
- const ProtocolDecl *proto = conformance->getProtocol ();
8665
8706
if (proto->isObjC () && getContext ().LangOpts .EnableDeserializationRecovery ) {
8666
8707
// Don't crash if inherited protocols are added or removed.
8667
8708
// This is limited to Objective-C protocols because we know their only
@@ -8702,12 +8743,39 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
8702
8743
return req.getKind () == RequirementKind::Conformance;
8703
8744
};
8704
8745
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 ;
8711
8779
}
8712
8780
}
8713
8781
0 commit comments