Skip to content

Commit e37071b

Browse files
committed
Add a new diagnostic group and documentation for the module-not-found failure which specifies that a missing module dependency can be found on a search path serialized in another Swift binary module dependency.
1 parent e67be5a commit e37071b

File tree

7 files changed

+69
-48
lines changed

7 files changed

+69
-48
lines changed

include/swift/AST/DiagnosticGroups.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ GROUP(ExistentialAny, "existential-any")
5050
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
5151
GROUP(IsolatedConformances, "isolated-conformances")
5252
GROUP(MemberImportVisibility, "member-import-visibility")
53+
GROUP(MissingModuleOnKnownPaths, "missing-module-on-known-paths")
5354
GROUP(MultipleInheritance, "multiple-inheritance")
5455
GROUP(MutableGlobalVariable, "mutable-global-variable")
5556
GROUP(NominalTypes, "nominal-types")

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,15 +2332,18 @@ ERROR(alignment_not_power_of_two,none,
23322332

23332333
// Dependency Scanning
23342334
ERROR(dependency_scan_module_not_found, none, "Unable to find module dependency: '%0'", (StringRef))
2335+
GROUPED_ERROR(dependency_scan_module_not_found_on_specified_search_paths, MissingModuleOnKnownPaths, none,
2336+
"Compilation search paths unable to resolve module dependency: '%0'", (StringRef))
23352337
NOTE(unresolved_import_location,none,
23362338
"also imported here", ())
23372339
NOTE(dependency_as_imported_by_main_module,none,
23382340
"a dependency of main module '%0'", (StringRef))
23392341
NOTE(dependency_as_imported_by, none,
23402342
"a dependency of %select{Swift|Clang}2 module '%0': '%1'", (StringRef, StringRef, bool))
23412343
NOTE(inherited_search_path_resolves_module,none,
2342-
"'%0' can be found on a search path used to build module '%1': '%2'. "
2343-
"These search paths are not inherited by the current compilation.", (StringRef, StringRef, StringRef))
2344+
"'%0' can be found using a search path that was specified when building module '%1' ('%2'). "
2345+
"This search path was not explicitly specified on the current compilation.", (StringRef, StringRef, StringRef))
2346+
23442347
ERROR(clang_dependency_scan_error, none, "Clang dependency scanner failure: %0", (StringRef))
23452348
ERROR(clang_header_dependency_scan_error, none, "Bridging header dependency scan failure: %0", (StringRef))
23462349

include/swift/DependencyScan/ModuleDependencyScanner.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,10 @@ class ModuleDependencyScanner {
203203
/// Assuming the \c `moduleImport` failed to resolve,
204204
/// iterate over all binary Swift module dependencies with serialized
205205
/// search paths and attempt to diagnose if the failed-to-resolve module
206-
/// can be found on any of them.
207-
void attemptToFindResolvingSerializedSearchPath(
206+
/// can be found on any of them. Returns the path containing
207+
/// the module, if one is found.
208+
std::optional<std::pair<ModuleDependencyID, std::string>>
209+
attemptToFindResolvingSerializedSearchPath(
208210
const ScannerImportStatementInfo &moduleImport,
209211
const ModuleDependenciesCache &cache, const SourceLoc &importLoc);
210212

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,8 +1656,27 @@ void ModuleDependencyScanner::diagnoseScannerFailure(
16561656
locInfo.bufferIdentifier, locInfo.lineNumber, locInfo.columnNumber);
16571657
}
16581658

1659-
Diagnostics.diagnose(importLoc, diag::dependency_scan_module_not_found,
1660-
moduleImport.importIdentifier);
1659+
// Attempt to determine if any of the binary Swift module dependencies contain
1660+
// serialized search paths where the missing module may be found. If yes,
1661+
// emit a specialized diagnostic letting the user know which search path
1662+
// is missing in current compilation.
1663+
auto resolvedModuleDefiningPath = attemptToFindResolvingSerializedSearchPath(
1664+
moduleImport, cache, importLoc);
1665+
if (resolvedModuleDefiningPath) {
1666+
Diagnostics.diagnose(
1667+
importLoc,
1668+
diag::dependency_scan_module_not_found_on_specified_search_paths,
1669+
moduleImport.importIdentifier);
1670+
Diagnostics.diagnose(importLoc, diag::inherited_search_path_resolves_module,
1671+
moduleImport.importIdentifier,
1672+
resolvedModuleDefiningPath->first.ModuleName,
1673+
resolvedModuleDefiningPath->second);
1674+
} else
1675+
Diagnostics.diagnose(importLoc, diag::dependency_scan_module_not_found,
1676+
moduleImport.importIdentifier);
1677+
1678+
// Emit notes for every link in the dependency chain from the root
1679+
// module-under-scan to the module whose import failed to resolve.
16611680
if (dependencyOf.has_value()) {
16621681
auto path = findPathToDependency(dependencyOf.value(), cache);
16631682
// We may fail to construct a path in some cases, such as a Swift overlay of
@@ -1703,6 +1722,8 @@ void ModuleDependencyScanner::diagnoseScannerFailure(
17031722
}
17041723
}
17051724

1725+
// Emit notes for every other location where the failed-to-resolve
1726+
// module is imported.
17061727
if (moduleImport.importLocations.size() > 1) {
17071728
for (size_t i = 1; i < moduleImport.importLocations.size(); ++i) {
17081729
auto locInfo = moduleImport.importLocations[i];
@@ -1711,8 +1732,6 @@ void ModuleDependencyScanner::diagnoseScannerFailure(
17111732
Diagnostics.diagnose(importLoc, diag::unresolved_import_location);
17121733
}
17131734
}
1714-
1715-
attemptToFindResolvingSerializedSearchPath(moduleImport, cache, importLoc);
17161735
}
17171736

17181737
static std::string getModuleDefiningPath(const ModuleDependencyInfo &info) {
@@ -1737,31 +1756,17 @@ static std::string getModuleDefiningPath(const ModuleDependencyInfo &info) {
17371756

17381757
// Relative to the `module.modulemap` or `.swiftinterface` or `.swiftmodule`,
17391758
// the defininig path is the parent directory of the file.
1740-
<<<<<<< Updated upstream
1741-
path = llvm::sys::path::parent_path(path);
1742-
1743-
// If the defining path is the top-level `.swiftmodule` directory,
1744-
// take one more step up.
1745-
if (llvm::sys::path::extension(path) == ".swiftmodule")
1746-
path = llvm::sys::path::parent_path(path);
1747-
1748-
// If the defining path is under `.framework/Modules/` directory,
1749-
// return the parent path containing the framework.
1750-
if (llvm::sys::path::filename(path) == "Modules" && llvm::sys::path::extension(llvm::sys::path::parent_path(path)) == ".framework")
1751-
path = llvm::sys::path::parent_path(llvm::sys::path::parent_path(path));
1752-
1753-
return path;
1754-
=======
17551759
return llvm::sys::path::parent_path(path).str();
1756-
>>>>>>> Stashed changes
17571760
}
17581761

1759-
void ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
1762+
std::optional<std::pair<ModuleDependencyID, std::string>>
1763+
ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
17601764
const ScannerImportStatementInfo &moduleImport,
17611765
const ModuleDependenciesCache &cache, const SourceLoc &importLoc) {
17621766
std::set<ModuleDependencyID> binarySwiftModuleDepIDs =
17631767
collectBinarySwiftDeps(cache);
17641768

1769+
std::optional<std::pair<ModuleDependencyID, std::string>> result;
17651770
for (const auto &binaryDepID : binarySwiftModuleDepIDs) {
17661771
auto binaryModInfo =
17671772
cache.findKnownDependency(binaryDepID).getAsSwiftBinaryModule();
@@ -1772,9 +1777,10 @@ void ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
17721777
// Note: this will permanently mutate this worker with additional search
17731778
// paths. That's fine because we are diagnosing a scan failure here, but
17741779
// worth being aware of.
1775-
withDependencyScanningWorker(
1776-
[&binaryModInfo, &moduleImport, &cache, &binaryDepID, &importLoc,
1777-
this](ModuleDependencyScanningWorker *ScanningWorker) {
1780+
result = withDependencyScanningWorker(
1781+
[&binaryModInfo, &moduleImport, &cache, this,
1782+
&binaryDepID](ModuleDependencyScanningWorker *ScanningWorker)
1783+
-> std::optional<std::pair<ModuleDependencyID, std::string>> {
17781784
ModuleDependencyVector result;
17791785
for (const auto &sp : binaryModInfo->serializedSearchPaths)
17801786
ScanningWorker->workerASTContext->addSearchPath(
@@ -1784,31 +1790,22 @@ void ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
17841790
getModuleImportIdentifier(moduleImport.importIdentifier),
17851791
cache.getModuleOutputPath(), cache.getSDKModuleOutputPath(),
17861792
cache.getScanService().getPrefixMapper());
1787-
if (!result.empty()) {
1788-
Diagnostics.diagnose(
1789-
importLoc, diag::inherited_search_path_resolves_module,
1790-
moduleImport.importIdentifier, binaryDepID.ModuleName,
1791-
getModuleDefiningPath(result[0].second));
1792-
}
1793+
if (!result.empty())
1794+
return std::make_pair(binaryDepID,
1795+
getModuleDefiningPath(result[0].second));
17931796

17941797
result = ScanningWorker->scanFilesystemForClangModuleDependency(
17951798
getModuleImportIdentifier(moduleImport.importIdentifier),
17961799
cache.getModuleOutputPath(), cache.getSDKModuleOutputPath(), {},
17971800
cache.getScanService().getPrefixMapper());
1798-
<<<<<<< Updated upstream
1799-
if (!result.empty()) {
1800-
Diagnostics.diagnose(
1801-
importLoc, diag::inherited_search_path_resolves_module,
1802-
moduleImport.importIdentifier, binaryDepID.ModuleName,
1803-
getModuleDefiningPath(result[0].second));
1804-
}
1805-
return result;
1806-
=======
18071801
if (!result.empty())
18081802
return std::make_pair(binaryDepID,
18091803
getModuleDefiningPath(result[0].second));
18101804
return std::nullopt;
1811-
>>>>>>> Stashed changes
18121805
});
1806+
if (result)
1807+
break;
18131808
}
1809+
1810+
return result;
18141811
}

test/ScanDependencies/cached-missing-module-found-in-serialized-paths.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
// CHECK: remark: Incremental module scan: Re-using serialized module scanning dependency cache from: '{{.*}}cache.moddepcache'.
2222
// CHECK: remark: Incremental module scan: Dependency info for module 'C' invalidated due to a modified input since last scan: '{{.*}}deps{{/|\\}}C.swiftinterface'.
2323
// CHECK: remark: Incremental module scan: Dependency info for module 'deps' invalidated due to an out-of-date dependency.
24-
// CHECK: error: Unable to find module dependency: 'C'
24+
// CHECK: error: Compilation search paths unable to resolve module dependency: 'C'
25+
// CHECK: note: 'C' can be found using a search path that was specified when building module 'B' ('{{.*}}moreDeps'). This search path was not explicitly specified on the current compilation.
2526
// CHECK: note: a dependency of main module 'deps'
26-
// CHECK: note: 'C' can be found on a search path used to build module 'B': '{{.*}}moreDeps'. These search paths are not inherited by the current compilation.
2727

2828
//--- moreDeps/C.swiftinterface
2929
// swift-interface-format-version: 1.0

test/ScanDependencies/diagnose-missing-module-found-in-serialized-paths.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
// RUN: %target-swift-frontend -scan-dependencies -o %t/deps.json %t/client.swift -I %t/deps -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import &> %t/output.txt
1010
// RUN: cat %t/output.txt | %FileCheck %s
1111

12-
// CHECK: error: Unable to find module dependency: 'C'
12+
// CHECK: error: Compilation search paths unable to resolve module dependency: 'C'
13+
// CHECK: note: 'C' can be found using a search path that was specified when building module 'B' ('{{.*}}moreDeps'). This search path was not explicitly specified on the current compilation.
1314
// CHECK: note: a dependency of Swift module 'B': '{{.*}}B.swiftmodule'
1415
// CHECK: note: a dependency of main module 'deps'
15-
// CHECK: note: 'C' can be found on a search path used to build module 'B': '{{.*}}moreDeps'. These search paths are not inherited by the current compilation.
1616

1717
//--- moreDeps/C.swiftinterface
1818
// swift-interface-format-version: 1.0
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Missing Module On Known Path From A Dependency Note (`MissingModuleOnKnownPaths`)
2+
3+
4+
This diagnostic group covers notes related to displaying information about a missing module dependency which the compiler is able to locate as present on a search path found in a loaded Swift binary module, but which is not specified to the current compilation.
5+
6+
As one example of a potential missing module diagnostic, suppose an imported module `Foo` is resolved to a Swift binary module which itself depends on module `Bar` and was built with an additional search path where `Bar` is located, and suppose that the client which imports `Foo` does not specify this search path:
7+
8+
```
9+
import Foo
10+
```
11+
12+
The Swift compiler would emit a module-not-found error and a note to inform the user of the missing search path containing `Bar` which was found serialized in `Foo`'s binary Swift module:
13+
14+
```
15+
error: Compilation search paths unable to resolve module dependency: 'Bar' [#MissingModuleOnKnownPaths]
16+
note: 'Bar' can be found using a search path that was specified when building module 'Foo' ('<Search Path>'). This search path was not specified on the current compilation.
17+
```
18+
Some prior versions of the Swift compiler erroneously inherited search paths from loaded binary Swift modules and used them to resolve other, subsequently-encountered module dependencies. All search paths required to resolve direct and transitive module dependencies must be explicitly specified on the compiler invocation which will encounter these dependencies.

0 commit comments

Comments
 (0)