Skip to content

Commit 550538f

Browse files
committed
[Dependency Scanning] Emit a warning when failing to load a binary module of a non-resilient dependency
This failure will most-likely result in the dependency query failure which will fail the scan. It will be helpful if the scanner emitted diagnostic for each such module it rejected to explain the reason why. Resolves rdar://142906530
1 parent f7fb099 commit 550538f

File tree

6 files changed

+89
-51
lines changed

6 files changed

+89
-51
lines changed

include/swift/AST/DiagnosticsSema.def

+8-2
Original file line numberDiff line numberDiff line change
@@ -1230,8 +1230,14 @@ REMARK(module_api_import_aliases,none,
12301230
"%select{, which reexports definition from %2|}3",
12311231
(const Decl *, ModuleDecl *, ModuleDecl *, bool))
12321232

1233-
REMARK(skip_module_invalid,none,"skip invalid swiftmodule: %0", (StringRef))
1234-
WARNING(skip_module_not_testable,none,"ignore swiftmodule built without '-enable-testing': %0", (StringRef))
1233+
REMARK(dependency_scan_skip_module_invalid,none,
1234+
"module file '%0' skipped by the dependency scan because it is "
1235+
"incompatible with this Swift compiler: %1", (StringRef, StringRef))
1236+
WARNING(skip_module_not_testable,none,
1237+
"ignore swiftmodule built without '-enable-testing': %0", (StringRef))
1238+
WARNING(dependency_scan_module_incompatible, none,
1239+
"module file '%0' is incompatible with this Swift compiler: %1",
1240+
(StringRef, StringRef))
12351241

12361242
REMARK(macro_loaded,none,
12371243
"loaded macro implementation module %0 from "

include/swift/Serialization/SerializedModuleLoader.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/ModuleDependencies.h"
1919
#include "swift/AST/ModuleLoader.h"
2020
#include "swift/AST/SearchPathOptions.h"
21+
#include "swift/Serialization/Validation.h"
2122
#include "llvm/Support/MemoryBuffer.h"
2223
#include "llvm/Support/PrefixMapper.h"
2324
#include "llvm/TargetParser/Triple.h"
@@ -165,7 +166,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
165166

166167
/// Scan the given serialized module file to determine dependencies.
167168
llvm::ErrorOr<ModuleDependencyInfo>
168-
scanModuleFile(Twine modulePath, bool isFramework, bool isTestableImport);
169+
scanModuleFile(Twine modulePath, bool isFramework,
170+
bool isTestableImport, bool isCandidateForTextualModule);
169171

170172
struct BinaryModuleImports {
171173
llvm::StringSet<> moduleImports;
@@ -267,6 +269,10 @@ class SerializedModuleLoaderBase : public ModuleLoader {
267269
InterfaceSubContextDelegate &delegate,
268270
llvm::PrefixMapper *mapper,
269271
bool isTestableImport) override;
272+
273+
/// A textual reason why the compiler rejected a binary module load
274+
/// attempt with a given status, to be used for diagnostic output.
275+
static std::optional<std::string> invalidModuleReason(serialization::Status status);
270276
};
271277

272278
/// Imports serialized Swift modules into an ASTContext.

lib/Frontend/ModuleInterfaceLoader.cpp

+2-41
Original file line numberDiff line numberDiff line change
@@ -325,45 +325,6 @@ struct ModuleRebuildInfo {
325325
return false;
326326
}
327327

328-
const char *invalidModuleReason(serialization::Status status) {
329-
using namespace serialization;
330-
switch (status) {
331-
case Status::FormatTooOld:
332-
return "compiled with an older version of the compiler";
333-
case Status::FormatTooNew:
334-
return "compiled with a newer version of the compiler";
335-
case Status::RevisionIncompatible:
336-
return "compiled with a different version of the compiler";
337-
case Status::ChannelIncompatible:
338-
return "compiled for a different distribution channel";
339-
case Status::NotInOSSA:
340-
return "module was not built with OSSA";
341-
case Status::MissingDependency:
342-
return "missing dependency";
343-
case Status::MissingUnderlyingModule:
344-
return "missing underlying module";
345-
case Status::CircularDependency:
346-
return "circular dependency";
347-
case Status::FailedToLoadBridgingHeader:
348-
return "failed to load bridging header";
349-
case Status::Malformed:
350-
return "malformed";
351-
case Status::MalformedDocumentation:
352-
return "malformed documentation";
353-
case Status::NameMismatch:
354-
return "name mismatch";
355-
case Status::TargetIncompatible:
356-
return "compiled for a different target platform";
357-
case Status::TargetTooNew:
358-
return "target platform newer than current platform";
359-
case Status::SDKMismatch:
360-
return "SDK does not match";
361-
case Status::Valid:
362-
return nullptr;
363-
}
364-
llvm_unreachable("bad status");
365-
}
366-
367328
/// Emits a diagnostic for all out-of-date compiled or forwarding modules
368329
/// encountered while trying to load a module.
369330
template<typename... DiagArgs>
@@ -406,9 +367,9 @@ struct ModuleRebuildInfo {
406367
// If there was a compiled module that wasn't able to be read, diagnose
407368
// the reason we couldn't read it.
408369
if (auto status = mod.serializationStatus) {
409-
if (auto reason = invalidModuleReason(*status)) {
370+
if (auto reason = SerializedModuleLoaderBase::invalidModuleReason(*status)) {
410371
diags.diagnose(loc, diag::compiled_module_invalid_reason,
411-
mod.path, reason);
372+
mod.path, reason.value());
412373
} else {
413374
diags.diagnose(loc, diag::compiled_module_invalid, mod.path);
414375
}

lib/Serialization/ScanningLoaders.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ std::error_code SwiftModuleScanner::findModuleFilesInDirectory(
6161
if (fs.exists(ModPath)) {
6262
// The module file will be loaded directly.
6363
auto dependencies =
64-
scanModuleFile(ModPath, IsFramework, isTestableDependencyLookup);
64+
scanModuleFile(ModPath, IsFramework,
65+
isTestableDependencyLookup,
66+
/* isCandidateForTextualModule */ false);
6567
if (dependencies) {
6668
this->dependencies = std::move(dependencies.get());
6769
return std::error_code();
@@ -164,8 +166,9 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
164166
Ctx.SearchPathOpts.ScannerModuleValidation) {
165167
assert(compiledCandidates.size() == 1 &&
166168
"Should only have 1 candidate module");
167-
auto BinaryDep = scanModuleFile(compiledCandidates[0], isFramework,
168-
isTestableImport);
169+
auto BinaryDep = scanModuleFile(compiledCandidates[0],
170+
isFramework, isTestableImport,
171+
/* isCandidateForTextualModule */ true);
169172
if (BinaryDep) {
170173
Result = *BinaryDep;
171174
return std::error_code();

lib/Serialization/SerializedModuleLoader.cpp

+53-4
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,45 @@ SerializedModuleLoaderBase::getModuleName(ASTContext &Ctx, StringRef modulePath,
304304
return ModuleFile::getModuleName(Ctx, modulePath, Name);
305305
}
306306

307+
std::optional<std::string> SerializedModuleLoaderBase::invalidModuleReason(serialization::Status status) {
308+
using namespace serialization;
309+
switch (status) {
310+
case Status::FormatTooOld:
311+
return "compiled with an older version of the compiler";
312+
case Status::FormatTooNew:
313+
return "compiled with a newer version of the compiler";
314+
case Status::RevisionIncompatible:
315+
return "compiled with a different version of the compiler";
316+
case Status::ChannelIncompatible:
317+
return "compiled for a different distribution channel";
318+
case Status::NotInOSSA:
319+
return "module was not built with OSSA";
320+
case Status::MissingDependency:
321+
return "missing dependency";
322+
case Status::MissingUnderlyingModule:
323+
return "missing underlying module";
324+
case Status::CircularDependency:
325+
return "circular dependency";
326+
case Status::FailedToLoadBridgingHeader:
327+
return "failed to load bridging header";
328+
case Status::Malformed:
329+
return "malformed";
330+
case Status::MalformedDocumentation:
331+
return "malformed documentation";
332+
case Status::NameMismatch:
333+
return "name mismatch";
334+
case Status::TargetIncompatible:
335+
return "compiled for a different target platform";
336+
case Status::TargetTooNew:
337+
return "target platform newer than current platform";
338+
case Status::SDKMismatch:
339+
return "SDK does not match";
340+
case Status::Valid:
341+
return std::nullopt;
342+
}
343+
llvm_unreachable("bad status");
344+
}
345+
307346
llvm::ErrorOr<llvm::StringSet<>>
308347
SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule(
309348
Twine modulePath, bool isFramework, bool isRequiredOSSAModules,
@@ -504,7 +543,8 @@ SerializedModuleLoaderBase::resolveMacroPlugin(const ExternalMacroPlugin &macro,
504543

505544
llvm::ErrorOr<ModuleDependencyInfo>
506545
SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework,
507-
bool isTestableImport) {
546+
bool isTestableImport,
547+
bool isCandidateForTextualModule) {
508548
const std::string moduleDocPath;
509549
const std::string sourceInfoPath;
510550

@@ -521,10 +561,19 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework,
521561

522562
if (Ctx.SearchPathOpts.ScannerModuleValidation) {
523563
// If failed to load, just ignore and return do not found.
524-
if (loadInfo.status != serialization::Status::Valid) {
564+
if (auto loadFailureReason = invalidModuleReason(loadInfo.status)) {
565+
// If no textual interface was found, then for this dependency
566+
// scanning query this was *the* module discovered, which means
567+
// it would be helpful to let the user know why the scanner
568+
// was not able to use it because the scan will ultimately fail to
569+
// resolve this dependency due to this incompatibility.
570+
if (!isCandidateForTextualModule)
571+
Ctx.Diags.diagnose(SourceLoc(), diag::dependency_scan_module_incompatible,
572+
modulePath.str(), loadFailureReason.value());
573+
525574
if (Ctx.LangOpts.EnableModuleLoadingRemarks)
526-
Ctx.Diags.diagnose(SourceLoc(), diag::skip_module_invalid,
527-
modulePath.str());
575+
Ctx.Diags.diagnose(SourceLoc(), diag::dependency_scan_skip_module_invalid,
576+
modulePath.str(), loadFailureReason.value());
528577
return std::make_error_code(std::errc::no_such_file_or_directory);
529578
}
530579

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: mkdir -p %t/clang-module-cache
3+
// RUN: mkdir -p %t/moduleInputs
4+
5+
// RUN: echo "Not Really a module" >> %t/moduleInputs/FooBar.swiftmodule
6+
7+
// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %t/moduleInputs -diagnostic-style llvm -scanner-module-validation 2>&1 | %FileCheck %s
8+
9+
import FooBar
10+
11+
// CHECK: warning: module file '{{.*}}{{/|\\}}moduleInputs{{/|\\}}FooBar.swiftmodule' is incompatible with this Swift compiler: malformed
12+
// CHECK: error: Unable to find module dependency: 'FooBar'
13+

0 commit comments

Comments
 (0)