Skip to content

Commit 60be4db

Browse files
committed
[Dependency Scanning] Diagnose an error when only finding incompatible Swift binary modules
When querying a Swift module, the scanner now also keeps track of all discovered candidate binary modules which are not compatible with current compilation. - If a Swift dependency is successfully resolved to a compatible binary module or a textual interface, a warning is emitted for every incompatible binary Swift module discovered along the way. - If a Swift dependency is not resolved, but incompatible module candidates were found, an error is emitted - while it is likely that the scan would fail downstream, it is also possible that an underlying Clang module dependency (with the same name) is successfuly resolved and the Swift lookup failure is ignored, which is still going to lead to failures most of the time if the client code assumes the presence of the Swift overlay module in this scenario. This change refactors common error reporting by the scanner into a 'ModuleDependencyIssueReporter' class, which also keeps track of all diagnosed failed lookups to avoid repeating diagnostics.
1 parent 439bd97 commit 60be4db

15 files changed

+300
-155
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,15 +1290,6 @@ REMARK(module_api_import_aliases,none,
12901290
"%select{, which reexports definition from %2|}3",
12911291
(const Decl *, ModuleDecl *, ModuleDecl *, bool))
12921292

1293-
REMARK(dependency_scan_skip_module_invalid,none,
1294-
"module file '%0' skipped by the dependency scan because it is "
1295-
"incompatible with this Swift compiler: %1", (StringRef, StringRef))
1296-
WARNING(skip_module_not_testable,none,
1297-
"ignore swiftmodule built without '-enable-testing': %0", (StringRef))
1298-
WARNING(dependency_scan_module_incompatible, none,
1299-
"module file '%0' is incompatible with this Swift compiler: %1",
1300-
(StringRef, StringRef))
1301-
13021293
REMARK(macro_loaded,none,
13031294
"loaded macro implementation module %0 from "
13041295
"%select{shared library '%2'|executable '%2'|"
@@ -2377,9 +2368,11 @@ ERROR(alignment_not_power_of_two,none,
23772368
"alignment value must be a power of two", ())
23782369

23792370
// Dependency Scanning
2380-
ERROR(dependency_scan_module_not_found, none, "Unable to find module dependency: '%0'", (StringRef))
2371+
ERROR(dependency_scan_module_not_found, none, "unable to resolve module dependency: '%0'", (StringRef))
2372+
23812373
GROUPED_ERROR(dependency_scan_module_not_found_on_specified_search_paths, MissingModuleOnKnownPaths, none,
2382-
"Compilation search paths unable to resolve module dependency: '%0'", (StringRef))
2374+
"compilation search paths unable to resolve module dependency: '%0'", (StringRef))
2375+
23832376
NOTE(unresolved_import_location,none,
23842377
"also imported here", ())
23852378
NOTE(dependency_as_imported_by_main_module,none,
@@ -2388,10 +2381,21 @@ NOTE(dependency_as_imported_by, none,
23882381
"a dependency of %select{Swift|Clang}2 module '%0': '%1'", (StringRef, StringRef, bool))
23892382
NOTE(inherited_search_path_resolves_module,none,
23902383
"'%0' can be found using a search path that was specified when building module '%1' ('%2'). "
2391-
"This search path was not explicitly specified on the current compilation.", (StringRef, StringRef, StringRef))
2384+
"This search path was not explicitly specified on the current compilation", (StringRef, StringRef, StringRef))
2385+
2386+
ERROR(dependency_scan_compatible_swift_module_not_found, none,
2387+
"unable to resolve Swift module dependency to a compatible module: '%0'",
2388+
(StringRef))
2389+
NOTE(dependency_scan_incompatible_module_found,none,
2390+
"found incompatible module '%0': %1", (StringRef, StringRef))
2391+
2392+
WARNING(dependency_scan_module_incompatible, none,
2393+
"module file '%0' is incompatible with this Swift compiler: %1",
2394+
(StringRef, StringRef))
2395+
2396+
ERROR(clang_dependency_scan_error, none, "clang dependency scanning failure: %0", (StringRef))
23922397

2393-
ERROR(clang_dependency_scan_error, none, "Clang dependency scanner failure: %0", (StringRef))
2394-
ERROR(clang_header_dependency_scan_error, none, "Bridging header dependency scan failure: %0", (StringRef))
2398+
ERROR(clang_header_dependency_scan_error, none, "bridging header dependency scanning failure: %0", (StringRef))
23952399

23962400
// Enum annotations
23972401
ERROR(indirect_case_without_payload,none,

include/swift/AST/ModuleDependencies.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ struct ScannerImportStatementInfo {
124124
uint32_t columnNumber;
125125
};
126126

127+
ScannerImportStatementInfo(std::string importIdentifier)
128+
: importIdentifier(importIdentifier), importLocations(),
129+
isExported(false), accessLevel(AccessLevel::Public) {}
130+
127131
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
128132
AccessLevel accessLevel)
129133
: importIdentifier(importIdentifier), importLocations(),

include/swift/DependencyScan/ModuleDependencyScanner.h

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ModuleDependencyScanningWorker {
4646
&alreadySeenModules);
4747

4848
/// Retrieve the module dependencies for the Swift module with the given name.
49-
ModuleDependencyVector scanFilesystemForSwiftModuleDependency(
49+
SwiftModuleScannerQueryResult scanFilesystemForSwiftModuleDependency(
5050
Identifier moduleName, bool isTestableImport = false);
5151

5252
/// Query dependency information for header dependencies
@@ -122,27 +122,67 @@ class SwiftDependencyTracker {
122122
SwiftDependencyTracker(std::shared_ptr<llvm::cas::ObjectStore> CAS,
123123
llvm::PrefixMapper *Mapper,
124124
const CompilerInvocation &CI);
125-
125+
126126
void startTracking(bool includeCommonDeps = true);
127127
void trackFile(const Twine &path);
128128
llvm::Expected<llvm::cas::ObjectProxy> createTreeFromDependencies();
129-
129+
130130
private:
131131
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
132132
std::shared_ptr<llvm::cas::ObjectStore> CAS;
133133
llvm::PrefixMapper *Mapper;
134-
134+
135135
struct FileEntry {
136136
llvm::cas::ObjectRef FileRef;
137137
size_t Size;
138-
138+
139139
FileEntry(llvm::cas::ObjectRef FileRef, size_t Size)
140-
: FileRef(FileRef), Size(Size) {}
140+
: FileRef(FileRef), Size(Size) {}
141141
};
142142
llvm::StringMap<FileEntry> CommonFiles;
143143
std::map<std::string, FileEntry> TrackedFiles;
144144
};
145145

146+
class ModuleDependencyIssueReporter {
147+
private:
148+
ModuleDependencyIssueReporter(DiagnosticEngine &Diagnostics)
149+
: Diagnostics(Diagnostics) {}
150+
151+
/// Diagnose scanner failure and attempt to reconstruct the dependency
152+
/// path from the main module to the missing dependency
153+
void diagnoseModuleNotFoundFailure(
154+
const ScannerImportStatementInfo &moduleImport,
155+
const ModuleDependenciesCache &cache,
156+
std::optional<ModuleDependencyID> dependencyOf,
157+
std::optional<std::pair<ModuleDependencyID, std::string>>
158+
resolvingSerializedSearchPath,
159+
std::optional<
160+
std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>>
161+
foundIncompatibleCandidates = std::nullopt);
162+
163+
/// Upon query failure, if incompatible binary module
164+
/// candidates were found, emit a failure diagnostic
165+
void diagnoseFailureOnOnlyIncompatibleCandidates(
166+
const ScannerImportStatementInfo &moduleImport,
167+
const std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>
168+
&candidates,
169+
const ModuleDependenciesCache &cache,
170+
std::optional<ModuleDependencyID> dependencyOf);
171+
172+
/// Emit warnings for each discovered binary Swift module
173+
/// which was incompatible with the current compilation
174+
/// when querying \c moduleName
175+
void warnOnIncompatibleCandidates(
176+
StringRef moduleName,
177+
const std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>
178+
&candidates);
179+
180+
DiagnosticEngine &Diagnostics;
181+
std::unordered_set<std::string> ReportedMissing;
182+
// Restrict access to the parent scanner class.
183+
friend class ModuleDependencyScanner;
184+
};
185+
146186
class ModuleDependencyScanner {
147187
public:
148188
ModuleDependencyScanner(SwiftDependencyScanningService &ScanningService,
@@ -246,7 +286,7 @@ class ModuleDependencyScanner {
246286
StringRef mainModuleName, ModuleDependenciesCache &cache,
247287
llvm::function_ref<void(ModuleDependencyID)> action);
248288

249-
/// Performance BridgingHeader Chaining.
289+
/// Perform Bridging Header Chaining.
250290
llvm::Error
251291
performBridgingHeaderChaining(const ModuleDependencyID &rootModuleID,
252292
ModuleDependenciesCache &cache,
@@ -261,12 +301,6 @@ class ModuleDependencyScanner {
261301
/// for a given module name.
262302
Identifier getModuleImportIdentifier(StringRef moduleName);
263303

264-
/// Diagnose scanner failure and attempt to reconstruct the dependency
265-
/// path from the main module to the missing dependency.
266-
void diagnoseScannerFailure(const ScannerImportStatementInfo &moduleImport,
267-
const ModuleDependenciesCache &cache,
268-
std::optional<ModuleDependencyID> dependencyOf);
269-
270304
/// Assuming the \c `moduleImport` failed to resolve,
271305
/// iterate over all binary Swift module dependencies with serialized
272306
/// search paths and attempt to diagnose if the failed-to-resolve module
@@ -275,12 +309,12 @@ class ModuleDependencyScanner {
275309
std::optional<std::pair<ModuleDependencyID, std::string>>
276310
attemptToFindResolvingSerializedSearchPath(
277311
const ScannerImportStatementInfo &moduleImport,
278-
const ModuleDependenciesCache &cache, const SourceLoc &importLoc);
312+
const ModuleDependenciesCache &cache);
279313

280314
private:
281315
const CompilerInvocation &ScanCompilerInvocation;
282316
ASTContext &ScanASTContext;
283-
DiagnosticEngine &Diagnostics;
317+
ModuleDependencyIssueReporter IssueReporter;
284318

285319
/// The available pool of workers for filesystem module search
286320
unsigned NumThreads;

include/swift/Serialization/ScanningLoaders.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@
1818
#include "swift/Serialization/SerializedModuleLoader.h"
1919

2020
namespace swift {
21+
22+
/// Result of looking up a Swift module on the current filesystem
23+
/// search paths.
24+
struct SwiftModuleScannerQueryResult {
25+
struct IncompatibleCandidate {
26+
std::string path;
27+
std::string incompatibilityReason;
28+
};
29+
30+
std::vector<IncompatibleCandidate> incompatibleCandidates;
31+
std::optional<ModuleDependencyInfo> foundDependencyInfo;
32+
};
33+
2134
/// A module "loader" that looks for .swiftinterface and .swiftmodule files
2235
/// for the purpose of determining dependencies, but does not attempt to
2336
/// load the module files.
@@ -60,7 +73,8 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
6073
std::vector<std::string> swiftModuleClangCC1CommandLineArgs;
6174

6275
public:
63-
std::optional<ModuleDependencyInfo> dependencies;
76+
std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate> incompatibleCandidates;
77+
std::optional<ModuleDependencyInfo> foundDependencyInfo;
6478

6579
SwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode,
6680
InterfaceSubContextDelegate &astDelegate,
@@ -74,7 +88,7 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
7488
swiftModuleClangCC1CommandLineArgs(swiftModuleClangCC1CommandLineArgs) {}
7589

7690
/// Perform a filesystem search for a Swift module with a given name
77-
llvm::SmallVector<std::pair<ModuleDependencyID, ModuleDependencyInfo>, 1>
91+
SwiftModuleScannerQueryResult
7892
lookupSwiftModule(Identifier moduleName, bool isTestableImport);
7993
};
8094
} // namespace swift

0 commit comments

Comments
 (0)