Skip to content

Commit 261f32c

Browse files
authored
Merge pull request #66139 from xymus/r-module-recovery
2 parents bc5e8ba + 4f66fcf commit 261f32c

File tree

9 files changed

+156
-59
lines changed

9 files changed

+156
-59
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ ERROR(modularization_issue_decl_moved,Fatal,
878878
(bool, DeclName, Identifier, Identifier))
879879
ERROR(modularization_issue_decl_type_changed,Fatal,
880880
"reference to %select{top-level|type}0 %1 broken by a context change; "
881-
"the details of %1 %select{from %2|}5 changed since building '%3'"
881+
"the declaration kind of %1 %select{from %2|}5 changed since building '%3'"
882882
"%select{|, it was in %2 and is now found in %4}5",
883883
(bool, DeclName, Identifier, StringRef, Identifier, bool))
884884
ERROR(modularization_issue_decl_not_found,Fatal,

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ namespace swift {
244244
/// Emit a remark after loading a module.
245245
bool EnableModuleLoadingRemarks = false;
246246

247+
/// Emit remarks about contextual inconsistencies in loaded modules.
248+
bool EnableModuleRecoveryRemarks = false;
249+
247250
/// Emit a remark when indexing a system module.
248251
bool EnableIndexingSystemModuleRemarks = false;
249252

include/swift/Option/Options.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,10 @@ def emit_cross_import_remarks : Flag<["-"], "Rcross-import">,
393393

394394
def remark_loading_module : Flag<["-"], "Rmodule-loading">,
395395
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
396-
HelpText<"Emit a remark and file path of each loaded module">;
396+
HelpText<"Emit remarks about loaded module">;
397+
def remark_module_recovery : Flag<["-"], "Rmodule-recovery">,
398+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
399+
HelpText<"Emit remarks about contextual inconsistencies in loaded modules">;
397400

398401
def remark_indexing_system_module : Flag<["-"], "Rindexing-system-module">,
399402
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
973973
Opts.EnableCrossImportRemarks = Args.hasArg(OPT_emit_cross_import_remarks);
974974

975975
Opts.EnableModuleLoadingRemarks = Args.hasArg(OPT_remark_loading_module);
976+
Opts.EnableModuleRecoveryRemarks = Args.hasArg(OPT_remark_module_recovery);
976977

977978
Opts.EnableIndexingSystemModuleRemarks = Args.hasArg(OPT_remark_indexing_system_module);
978979

lib/Serialization/Deserialization.cpp

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ void UnsafeDeserializationError::anchor() {}
161161
const char ModularizationError::ID = '\0';
162162
void ModularizationError::anchor() {}
163163

164-
static llvm::Error consumeErrorIfXRefNonLoadedModule(llvm::Error &&error);
165-
166164
/// Skips a single record in the bitstream.
167165
///
168166
/// Destroys the stream position if the next entry is not a record.
@@ -235,21 +233,15 @@ void ExtensionError::diagnose(const ModuleFile *MF) const {
235233
diag::modularization_issue_side_effect_extension_error);
236234
}
237235

238-
llvm::Error ModuleFile::diagnoseFatal(llvm::Error error) const {
239-
240-
auto &ctx = getContext();
241-
if (FileContext) {
242-
if (ctx.LangOpts.EnableDeserializationRecovery) {
243-
// Attempt to report relevant errors as diagnostics.
244-
// At this time, only ModularizationErrors are reported directly. They
245-
// can get here either directly or as underlying causes to a TypeError or
246-
// and ExtensionError.
247-
auto handleModularizationError =
248-
[&](const ModularizationError &modularError) -> llvm::Error {
249-
modularError.diagnose(this);
250-
return llvm::Error::success();
251-
};
252-
error = llvm::handleErrors(std::move(error),
236+
llvm::Error
237+
ModuleFile::diagnoseModularizationError(llvm::Error error,
238+
DiagnosticBehavior limit) const {
239+
auto handleModularizationError =
240+
[&](const ModularizationError &modularError) -> llvm::Error {
241+
modularError.diagnose(this, limit);
242+
return llvm::Error::success();
243+
};
244+
llvm::Error outError = llvm::handleErrors(std::move(error),
253245
handleModularizationError,
254246
[&](TypeError &typeError) -> llvm::Error {
255247
if (typeError.diagnoseUnderlyingReason(handleModularizationError)) {
@@ -266,6 +258,16 @@ llvm::Error ModuleFile::diagnoseFatal(llvm::Error error) const {
266258
return llvm::make_error<ExtensionError>(std::move(extError));
267259
});
268260

261+
return outError;
262+
}
263+
264+
llvm::Error ModuleFile::diagnoseFatal(llvm::Error error) const {
265+
266+
auto &ctx = getContext();
267+
if (FileContext) {
268+
if (ctx.LangOpts.EnableDeserializationRecovery) {
269+
error = diagnoseModularizationError(std::move(error));
270+
269271
// If no error is left, it was reported as a diagnostic. There's no
270272
// need to crash.
271273
if (!error)
@@ -1540,7 +1542,7 @@ ModuleFile::getSubstitutionMapChecked(serialization::SubstitutionMapID id) {
15401542
for (auto typeID : replacementTypeIDs) {
15411543
auto typeOrError = getTypeChecked(typeID);
15421544
if (!typeOrError) {
1543-
consumeError(typeOrError.takeError());
1545+
diagnoseAndConsumeError(typeOrError.takeError());
15441546
continue;
15451547
}
15461548
replacementTypes.push_back(typeOrError.get());
@@ -1795,7 +1797,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
17951797
if (maybeType.errorIsA<FatalDeserializationError>())
17961798
return maybeType.takeError();
17971799
// FIXME: Don't throw away the inner error's information.
1798-
consumeError(maybeType.takeError());
1800+
diagnoseAndConsumeError(maybeType.takeError());
17991801
return llvm::make_error<XRefError>("couldn't decode type",
18001802
pathTrace, name);
18011803
}
@@ -2165,7 +2167,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
21652167
return maybeType.takeError();
21662168

21672169
// FIXME: Don't throw away the inner error's information.
2168-
consumeError(maybeType.takeError());
2170+
diagnoseAndConsumeError(maybeType.takeError());
21692171
return llvm::make_error<XRefError>("couldn't decode type",
21702172
pathTrace, memberName);
21712173
}
@@ -3004,7 +3006,7 @@ class DeclDeserializer {
30043006

30053007
auto maybeType = MF.getTypeChecked(typeID);
30063008
if (!maybeType) {
3007-
llvm::consumeError(maybeType.takeError());
3009+
MF.diagnoseAndConsumeError(maybeType.takeError());
30083010
continue;
30093011
}
30103012
inheritedTypes.push_back(
@@ -3330,10 +3332,10 @@ class DeclDeserializer {
33303332
return overriddenOrError.takeError();
33313333
} else if (MF.allowCompilerErrors()) {
33323334
// Drop overriding relationship when allowing errors.
3333-
llvm::consumeError(overriddenOrError.takeError());
3335+
MF.diagnoseAndConsumeError(overriddenOrError.takeError());
33343336
overridden = nullptr;
33353337
} else {
3336-
llvm::consumeError(overriddenOrError.takeError());
3338+
MF.diagnoseAndConsumeError(overriddenOrError.takeError());
33373339
if (overriddenAffectsABI || !ctx.LangOpts.EnableDeserializationRecovery) {
33383340
return llvm::make_error<OverrideError>(name, errorFlags,
33393341
numVTableEntries);
@@ -3477,7 +3479,7 @@ class DeclDeserializer {
34773479
if (overridden.errorIsA<FatalDeserializationError>())
34783480
return overridden.takeError();
34793481

3480-
llvm::consumeError(overridden.takeError());
3482+
MF.diagnoseAndConsumeError(overridden.takeError());
34813483

34823484
return llvm::make_error<OverrideError>(
34833485
name, getErrorFlags(), numVTableEntries);
@@ -3589,7 +3591,7 @@ class DeclDeserializer {
35893591

35903592
// FIXME: This is actually wrong. We can't just drop stored properties
35913593
// willy-nilly if the struct is @frozen.
3592-
consumeError(backingDecl.takeError());
3594+
MF.diagnoseAndConsumeError(backingDecl.takeError());
35933595
return var;
35943596
}
35953597

@@ -3806,15 +3808,15 @@ class DeclDeserializer {
38063808
overridden = overriddenOrError.get();
38073809
} else {
38083810
if (overriddenAffectsABI || !ctx.LangOpts.EnableDeserializationRecovery) {
3809-
llvm::consumeError(overriddenOrError.takeError());
3811+
MF.diagnoseAndConsumeError(overriddenOrError.takeError());
38103812
return llvm::make_error<OverrideError>(name, errorFlags,
38113813
numVTableEntries);
38123814
}
38133815
// Pass through deserialization errors.
38143816
if (overriddenOrError.errorIsA<FatalDeserializationError>())
38153817
return overriddenOrError.takeError();
38163818

3817-
llvm::consumeError(overriddenOrError.takeError());
3819+
MF.diagnoseAndConsumeError(overriddenOrError.takeError());
38183820
overridden = nullptr;
38193821
}
38203822

@@ -4079,7 +4081,7 @@ class DeclDeserializer {
40794081
if (!subMapOrError) {
40804082
// If the underlying type references internal details, ignore it.
40814083
auto unconsumedError =
4082-
consumeErrorIfXRefNonLoadedModule(subMapOrError.takeError());
4084+
MF.consumeExpectedError(subMapOrError.takeError());
40834085
if (unconsumedError)
40844086
return std::move(unconsumedError);
40854087
} else {
@@ -4136,7 +4138,7 @@ class DeclDeserializer {
41364138
return pattern.takeError();
41374139

41384140
// Silently drop the pattern...
4139-
llvm::consumeError(pattern.takeError());
4141+
MF.diagnoseAndConsumeError(pattern.takeError());
41404142
// ...but continue to read any further patterns we're expecting.
41414143
continue;
41424144
}
@@ -4654,7 +4656,7 @@ class DeclDeserializer {
46544656
// Pass through deserialization errors.
46554657
if (overridden.errorIsA<FatalDeserializationError>())
46564658
return overridden.takeError();
4657-
llvm::consumeError(overridden.takeError());
4659+
MF.diagnoseAndConsumeError(overridden.takeError());
46584660

46594661
DeclDeserializationError::Flags errorFlags;
46604662
return llvm::make_error<OverrideError>(
@@ -5178,7 +5180,7 @@ llvm::Error DeclDeserializer::deserializeCustomAttrs() {
51785180
// is safe to drop when it can't be deserialized.
51795181
// rdar://problem/56599179. When allowing errors we're doing a best
51805182
// effort to create a module, so ignore in that case as well.
5181-
consumeError(deserialized.takeError());
5183+
MF.diagnoseAndConsumeError(deserialized.takeError());
51825184
} else
51835185
return deserialized.takeError();
51845186
} else if (!deserialized.get() && MF.allowCompilerErrors()) {
@@ -6127,7 +6129,7 @@ Expected<Type> DESERIALIZE_TYPE(NAME_ALIAS_TYPE)(
61276129

61286130
// We're going to recover by falling back to the underlying type, so
61296131
// just ignore the error.
6130-
llvm::consumeError(aliasOrError.takeError());
6132+
MF.diagnoseAndConsumeError(aliasOrError.takeError());
61316133
}
61326134

61336135
if (!alias || !alias->getDeclaredInterfaceType()->isEqual(underlyingType)) {
@@ -7364,13 +7366,16 @@ Decl *handleErrorAndSupplyMissingProtoMember(ASTContext &context,
73647366
return suppliedMissingMember;
73657367
}
73667368

7367-
Decl *handleErrorAndSupplyMissingMiscMember(llvm::Error &&error) {
7368-
llvm::consumeError(std::move(error));
7369+
Decl *
7370+
ModuleFile::handleErrorAndSupplyMissingMiscMember(llvm::Error &&error) const {
7371+
diagnoseAndConsumeError(std::move(error));
73697372
return nullptr;
73707373
}
73717374

7372-
Decl *handleErrorAndSupplyMissingMember(ASTContext &context, Decl *container,
7373-
llvm::Error &&error) {
7375+
Decl *
7376+
ModuleFile::handleErrorAndSupplyMissingMember(ASTContext &context,
7377+
Decl *container,
7378+
llvm::Error &&error) const {
73747379
// Drop the member if it had a problem.
73757380
// FIXME: Handle overridable members in class extensions too, someday.
73767381
if (auto *containingClass = dyn_cast<ClassDecl>(container)) {
@@ -7444,14 +7449,14 @@ void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) {
74447449
}
74457450
}
74467451

7447-
static llvm::Error consumeErrorIfXRefNonLoadedModule(llvm::Error &&error) {
7452+
llvm::Error ModuleFile::consumeExpectedError(llvm::Error &&error) {
74487453
// Missing module errors are most likely caused by an
74497454
// implementation-only import hiding types and decls.
74507455
// rdar://problem/60291019
74517456
if (error.isA<XRefNonLoadedModuleError>() ||
74527457
error.isA<UnsafeDeserializationError>() ||
74537458
error.isA<ModularizationError>()) {
7454-
consumeError(std::move(error));
7459+
diagnoseAndConsumeError(std::move(error));
74557460
return llvm::Error::success();
74567461
}
74577462

@@ -7465,7 +7470,7 @@ static llvm::Error consumeErrorIfXRefNonLoadedModule(llvm::Error &&error) {
74657470
if (TE->underlyingReasonIsA<XRefNonLoadedModuleError>() ||
74667471
TE->underlyingReasonIsA<UnsafeDeserializationError>() ||
74677472
TE->underlyingReasonIsA<ModularizationError>()) {
7468-
consumeError(std::move(errorInfo));
7473+
diagnoseAndConsumeError(std::move(errorInfo));
74697474
return llvm::Error::success();
74707475
}
74717476

@@ -7475,6 +7480,19 @@ static llvm::Error consumeErrorIfXRefNonLoadedModule(llvm::Error &&error) {
74757480
return std::move(error);
74767481
}
74777482

7483+
void ModuleFile::diagnoseAndConsumeError(llvm::Error error) const {
7484+
auto &ctx = getContext();
7485+
if (ctx.LangOpts.EnableModuleRecoveryRemarks) {
7486+
error = diagnoseModularizationError(std::move(error),
7487+
DiagnosticBehavior::Remark);
7488+
// If error was already diagnosed it was also consumed.
7489+
if (!error)
7490+
return;
7491+
}
7492+
7493+
consumeError(std::move(error));
7494+
}
7495+
74787496
namespace {
74797497
class LazyConformanceLoaderInfo final
74807498
: llvm::TrailingObjects<LazyConformanceLoaderInfo,
@@ -7538,12 +7556,12 @@ ModuleFile::loadAllConformances(const Decl *D, uint64_t contextData,
75387556

75397557
if (!conformance) {
75407558
auto unconsumedError =
7541-
consumeErrorIfXRefNonLoadedModule(conformance.takeError());
7559+
consumeExpectedError(conformance.takeError());
75427560
if (unconsumedError) {
75437561
// Ignore if allowing errors, it's just doing a best effort to produce
75447562
// *some* module anyway.
75457563
if (allowCompilerErrors())
7546-
consumeError(std::move(unconsumedError));
7564+
diagnoseAndConsumeError(std::move(unconsumedError));
75477565
else
75487566
fatal(std::move(unconsumedError));
75497567
}
@@ -7633,7 +7651,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
76337651
if (maybeConformance) {
76347652
reqConformances.push_back(maybeConformance.get());
76357653
} else if (allowCompilerErrors()) {
7636-
consumeError(maybeConformance.takeError());
7654+
diagnoseAndConsumeError(maybeConformance.takeError());
76377655
reqConformances.push_back(ProtocolConformanceRef::forInvalid());
76387656
} else {
76397657
fatal(maybeConformance.takeError());
@@ -7701,7 +7719,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
77017719
second = *secondOrError;
77027720
} else if (getContext().LangOpts.EnableDeserializationRecovery) {
77037721
second = ErrorType::get(getContext());
7704-
consumeError(secondOrError.takeError());
7722+
diagnoseAndConsumeError(secondOrError.takeError());
77057723
} else {
77067724
fatal(secondOrError.takeError());
77077725
}
@@ -7711,7 +7729,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
77117729
third = cast_or_null<TypeDecl>(*thirdOrError);
77127730
} else if (getContext().LangOpts.EnableDeserializationRecovery) {
77137731
third = nullptr;
7714-
consumeError(thirdOrError.takeError());
7732+
diagnoseAndConsumeError(thirdOrError.takeError());
77157733
} else {
77167734
fatal(thirdOrError.takeError());
77177735
}
@@ -7752,7 +7770,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
77527770
if (deserializedReq) {
77537771
req = cast_or_null<ValueDecl>(*deserializedReq);
77547772
} else if (getContext().LangOpts.EnableDeserializationRecovery) {
7755-
consumeError(deserializedReq.takeError());
7773+
diagnoseAndConsumeError(deserializedReq.takeError());
77567774
req = nullptr;
77577775
needToFillInOpaqueValueWitnesses = true;
77587776
} else {
@@ -7769,7 +7787,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
77697787
// In that case, we want the conformance to still be available, but
77707788
// we can't make use of the relationship to the underlying decl.
77717789
} else if (getContext().LangOpts.EnableDeserializationRecovery) {
7772-
consumeError(deserializedWitness.takeError());
7790+
diagnoseAndConsumeError(deserializedWitness.takeError());
77737791
isOpaque = true;
77747792
witness = nullptr;
77757793
} else {
@@ -7802,7 +7820,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
78027820
if (witnessSubstitutions.errorIsA<XRefNonLoadedModuleError>() ||
78037821
witnessSubstitutions.errorIsA<UnsafeDeserializationError>() ||
78047822
allowCompilerErrors()) {
7805-
consumeError(witnessSubstitutions.takeError());
7823+
diagnoseAndConsumeError(witnessSubstitutions.takeError());
78067824
isOpaque = true;
78077825
}
78087826
else

0 commit comments

Comments
 (0)