Skip to content

Commit 814ca43

Browse files
authored
Merge pull request #66186 from xymus/force-workaround
[Serialization] Add flag to force unsafe recovery from some xref failures
2 parents 60ef958 + d50f20e commit 814ca43

File tree

6 files changed

+52
-10
lines changed

6 files changed

+52
-10
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,10 @@ NOTE(modularization_issue_side_effect_type_error,none,
893893
"could not deserialize type for %0",
894894
(DeclName))
895895

896+
WARNING(modularization_issue_worked_around,none,
897+
"attempting forced recovery enabled by -experimental-force-workaround-broken-modules",
898+
())
899+
896900
ERROR(reserved_member_name,none,
897901
"type member must not be named %0, since it would conflict with the"
898902
" 'foo.%1' expression", (DeclName, StringRef))

include/swift/Basic/LangOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,11 @@ namespace swift {
399399
bool EnableDeserializationSafety =
400400
::getenv("SWIFT_ENABLE_DESERIALIZATION_SAFETY");
401401

402+
/// Attempt to recover for imported modules with broken modularization
403+
/// in an unsafe way. Currently applies only to xrefs where the target
404+
/// decl moved to a different module that is already loaded.
405+
bool ForceWorkaroundBrokenModules = false;
406+
402407
/// Whether to enable the new operator decl and precedencegroup lookup
403408
/// behavior. This is a staging flag, and will be removed in the future.
404409
bool EnableNewOperatorLookup = false;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,10 @@ def disable_deserialization_safety :
588588
Flag<["-"], "disable-deserialization-safety">,
589589
HelpText<"Don't avoid reading potentially unsafe decls in swiftmodules">;
590590

591+
def force_workaround_broken_modules :
592+
Flag<["-"], "experimental-force-workaround-broken-modules">,
593+
HelpText<"Attempt unsafe recovery for imported modules with broken modularization">;
594+
591595
def enable_experimental_string_processing :
592596
Flag<["-"], "enable-experimental-string-processing">,
593597
HelpText<"Enable experimental string processing">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
600600
Opts.EnableAccessControl
601601
= A->getOption().matches(OPT_enable_access_control);
602602
}
603+
Opts.ForceWorkaroundBrokenModules
604+
|= Args.hasArg(OPT_force_workaround_broken_modules);
603605

604606
// Whether '/.../' regex literals are enabled. This implies experimental
605607
// string processing.

lib/Serialization/Deserialization.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,8 +1885,10 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
18851885
}
18861886

18871887
auto getXRefDeclNameForError = [&]() -> DeclName {
1888+
BCOffsetRAII restoreOffset(DeclTypeCursor);
18881889
DeclName result = pathTrace.getLastName();
1889-
while (--pathLen) {
1890+
uint32_t namePathLen = pathLen;
1891+
while (--namePathLen) {
18901892
llvm::BitstreamEntry entry =
18911893
fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
18921894
if (entry.Kind != llvm::BitstreamEntry::Record)
@@ -1951,8 +1953,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
19511953
// up to the caller to recover if possible.
19521954

19531955
// Look for types and value decls in other modules. This extra information
1954-
// is mostly for compiler engineers to understand a likely solution at a
1955-
// quick glance.
1956+
// will be used for diagnostics by the caller logic.
19561957
SmallVector<char, 64> strScratch;
19571958

19581959
auto errorKind = ModularizationError::Kind::DeclNotFound;
@@ -2027,13 +2028,31 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
20272028
auto declName = getXRefDeclNameForError();
20282029
auto expectedIn = baseModule->getName();
20292030
auto referencedFrom = getName();
2030-
return llvm::make_error<ModularizationError>(declName,
2031-
isType,
2032-
errorKind,
2033-
expectedIn,
2034-
referencedFrom,
2035-
foundIn,
2036-
pathTrace);
2031+
auto error = llvm::make_error<ModularizationError>(declName,
2032+
isType,
2033+
errorKind,
2034+
expectedIn,
2035+
referencedFrom,
2036+
foundIn,
2037+
pathTrace);
2038+
2039+
// If we want to workaround broken modularization, we can keep going if
2040+
// we found a matching top-level decl in a different module. This is
2041+
// obviously dangerous as it could just be some other decl that happens to
2042+
// match.
2043+
if (getContext().LangOpts.ForceWorkaroundBrokenModules &&
2044+
errorKind == ModularizationError::Kind::DeclMoved &&
2045+
!values.empty()) {
2046+
// Print the error as a remark and notify of the recovery attempt.
2047+
getContext().Diags.diagnose(getSourceLoc(),
2048+
diag::modularization_issue_worked_around);
2049+
llvm::handleAllErrors(std::move(error),
2050+
[&](const ModularizationError &modularError) {
2051+
modularError.diagnose(this, DiagnosticBehavior::Note);
2052+
});
2053+
} else {
2054+
return std::move(error);
2055+
}
20372056
}
20382057

20392058
// Filters for values discovered in the remaining path pieces.

test/Serialization/modularization-error.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
// RUN: | %FileCheck --check-prefixes CHECK,CHECK-MOVED %s
1515
// CHECK-MOVED: LibWithXRef.swiftmodule:1:1: error: reference to type 'MyType' broken by a context change; 'MyType' was expected to be in 'A', but now a candidate is found only in 'B'
1616

17+
/// Force working around the broken modularization to get a result and no errors.
18+
// RUN: %target-swift-frontend -emit-sil %t/LibWithXRef.swiftmodule -module-name LibWithXRef -I %t \
19+
// RUN: -experimental-force-workaround-broken-modules 2>&1 \
20+
// RUN: | %FileCheck --check-prefixes CHECK-WORKAROUND %s
21+
// CHECK-WORKAROUND: warning: attempting forced recovery enabled by -experimental-force-workaround-broken-modules
22+
// CHECK-WORKAROUND: note: reference to type 'MyType' broken by a context change; 'MyType' was expected to be in 'A', but now a candidate is found only in 'B'
23+
// CHECK-WORKAROUND: func foo() -> some Proto
24+
1725
/// Change MyType into a function.
1826
// RUN: %target-swift-frontend %t/LibTypeChanged.swift -emit-module-path %t/A.swiftmodule -module-name A
1927
// RUN: %target-swift-frontend %t/Empty.swift -emit-module-path %t/B.swiftmodule -module-name B

0 commit comments

Comments
 (0)