mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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.
This commit is contained in:
@@ -50,6 +50,7 @@ GROUP(ExistentialAny, "existential-any")
|
|||||||
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
|
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
|
||||||
GROUP(IsolatedConformances, "isolated-conformances")
|
GROUP(IsolatedConformances, "isolated-conformances")
|
||||||
GROUP(MemberImportVisibility, "member-import-visibility")
|
GROUP(MemberImportVisibility, "member-import-visibility")
|
||||||
|
GROUP(MissingModuleOnKnownPaths, "missing-module-on-known-paths")
|
||||||
GROUP(MultipleInheritance, "multiple-inheritance")
|
GROUP(MultipleInheritance, "multiple-inheritance")
|
||||||
GROUP(MutableGlobalVariable, "mutable-global-variable")
|
GROUP(MutableGlobalVariable, "mutable-global-variable")
|
||||||
GROUP(NominalTypes, "nominal-types")
|
GROUP(NominalTypes, "nominal-types")
|
||||||
|
|||||||
@@ -2332,6 +2332,8 @@ ERROR(alignment_not_power_of_two,none,
|
|||||||
|
|
||||||
// Dependency Scanning
|
// Dependency Scanning
|
||||||
ERROR(dependency_scan_module_not_found, none, "Unable to find module dependency: '%0'", (StringRef))
|
ERROR(dependency_scan_module_not_found, none, "Unable to find module dependency: '%0'", (StringRef))
|
||||||
|
GROUPED_ERROR(dependency_scan_module_not_found_on_specified_search_paths, MissingModuleOnKnownPaths, none,
|
||||||
|
"Compilation search paths unable to resolve module dependency: '%0'", (StringRef))
|
||||||
NOTE(unresolved_import_location,none,
|
NOTE(unresolved_import_location,none,
|
||||||
"also imported here", ())
|
"also imported here", ())
|
||||||
NOTE(dependency_as_imported_by_main_module,none,
|
NOTE(dependency_as_imported_by_main_module,none,
|
||||||
@@ -2339,8 +2341,9 @@ NOTE(dependency_as_imported_by_main_module,none,
|
|||||||
NOTE(dependency_as_imported_by, none,
|
NOTE(dependency_as_imported_by, none,
|
||||||
"a dependency of %select{Swift|Clang}2 module '%0': '%1'", (StringRef, StringRef, bool))
|
"a dependency of %select{Swift|Clang}2 module '%0': '%1'", (StringRef, StringRef, bool))
|
||||||
NOTE(inherited_search_path_resolves_module,none,
|
NOTE(inherited_search_path_resolves_module,none,
|
||||||
"'%0' can be found on a search path used to build module '%1': '%2'. "
|
"'%0' can be found using a search path that was specified when building module '%1' ('%2'). "
|
||||||
"These search paths are not inherited by the current compilation.", (StringRef, StringRef, StringRef))
|
"This search path was not explicitly specified on the current compilation.", (StringRef, StringRef, StringRef))
|
||||||
|
|
||||||
ERROR(clang_dependency_scan_error, none, "Clang dependency scanner failure: %0", (StringRef))
|
ERROR(clang_dependency_scan_error, none, "Clang dependency scanner failure: %0", (StringRef))
|
||||||
ERROR(clang_header_dependency_scan_error, none, "Bridging header dependency scan failure: %0", (StringRef))
|
ERROR(clang_header_dependency_scan_error, none, "Bridging header dependency scan failure: %0", (StringRef))
|
||||||
|
|
||||||
|
|||||||
@@ -203,8 +203,10 @@ private:
|
|||||||
/// Assuming the \c `moduleImport` failed to resolve,
|
/// Assuming the \c `moduleImport` failed to resolve,
|
||||||
/// iterate over all binary Swift module dependencies with serialized
|
/// iterate over all binary Swift module dependencies with serialized
|
||||||
/// search paths and attempt to diagnose if the failed-to-resolve module
|
/// search paths and attempt to diagnose if the failed-to-resolve module
|
||||||
/// can be found on any of them.
|
/// can be found on any of them. Returns the path containing
|
||||||
void attemptToFindResolvingSerializedSearchPath(
|
/// the module, if one is found.
|
||||||
|
std::optional<std::pair<ModuleDependencyID, std::string>>
|
||||||
|
attemptToFindResolvingSerializedSearchPath(
|
||||||
const ScannerImportStatementInfo &moduleImport,
|
const ScannerImportStatementInfo &moduleImport,
|
||||||
const ModuleDependenciesCache &cache, const SourceLoc &importLoc);
|
const ModuleDependenciesCache &cache, const SourceLoc &importLoc);
|
||||||
|
|
||||||
|
|||||||
@@ -1656,8 +1656,27 @@ void ModuleDependencyScanner::diagnoseScannerFailure(
|
|||||||
locInfo.bufferIdentifier, locInfo.lineNumber, locInfo.columnNumber);
|
locInfo.bufferIdentifier, locInfo.lineNumber, locInfo.columnNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
Diagnostics.diagnose(importLoc, diag::dependency_scan_module_not_found,
|
// Attempt to determine if any of the binary Swift module dependencies contain
|
||||||
moduleImport.importIdentifier);
|
// serialized search paths where the missing module may be found. If yes,
|
||||||
|
// emit a specialized diagnostic letting the user know which search path
|
||||||
|
// is missing in current compilation.
|
||||||
|
auto resolvedModuleDefiningPath = attemptToFindResolvingSerializedSearchPath(
|
||||||
|
moduleImport, cache, importLoc);
|
||||||
|
if (resolvedModuleDefiningPath) {
|
||||||
|
Diagnostics.diagnose(
|
||||||
|
importLoc,
|
||||||
|
diag::dependency_scan_module_not_found_on_specified_search_paths,
|
||||||
|
moduleImport.importIdentifier);
|
||||||
|
Diagnostics.diagnose(importLoc, diag::inherited_search_path_resolves_module,
|
||||||
|
moduleImport.importIdentifier,
|
||||||
|
resolvedModuleDefiningPath->first.ModuleName,
|
||||||
|
resolvedModuleDefiningPath->second);
|
||||||
|
} else
|
||||||
|
Diagnostics.diagnose(importLoc, diag::dependency_scan_module_not_found,
|
||||||
|
moduleImport.importIdentifier);
|
||||||
|
|
||||||
|
// Emit notes for every link in the dependency chain from the root
|
||||||
|
// module-under-scan to the module whose import failed to resolve.
|
||||||
if (dependencyOf.has_value()) {
|
if (dependencyOf.has_value()) {
|
||||||
auto path = findPathToDependency(dependencyOf.value(), cache);
|
auto path = findPathToDependency(dependencyOf.value(), cache);
|
||||||
// We may fail to construct a path in some cases, such as a Swift overlay of
|
// We may fail to construct a path in some cases, such as a Swift overlay of
|
||||||
@@ -1703,6 +1722,8 @@ void ModuleDependencyScanner::diagnoseScannerFailure(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit notes for every other location where the failed-to-resolve
|
||||||
|
// module is imported.
|
||||||
if (moduleImport.importLocations.size() > 1) {
|
if (moduleImport.importLocations.size() > 1) {
|
||||||
for (size_t i = 1; i < moduleImport.importLocations.size(); ++i) {
|
for (size_t i = 1; i < moduleImport.importLocations.size(); ++i) {
|
||||||
auto locInfo = moduleImport.importLocations[i];
|
auto locInfo = moduleImport.importLocations[i];
|
||||||
@@ -1711,8 +1732,6 @@ void ModuleDependencyScanner::diagnoseScannerFailure(
|
|||||||
Diagnostics.diagnose(importLoc, diag::unresolved_import_location);
|
Diagnostics.diagnose(importLoc, diag::unresolved_import_location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attemptToFindResolvingSerializedSearchPath(moduleImport, cache, importLoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getModuleDefiningPath(const ModuleDependencyInfo &info) {
|
static std::string getModuleDefiningPath(const ModuleDependencyInfo &info) {
|
||||||
@@ -1737,31 +1756,17 @@ static std::string getModuleDefiningPath(const ModuleDependencyInfo &info) {
|
|||||||
|
|
||||||
// Relative to the `module.modulemap` or `.swiftinterface` or `.swiftmodule`,
|
// Relative to the `module.modulemap` or `.swiftinterface` or `.swiftmodule`,
|
||||||
// the defininig path is the parent directory of the file.
|
// the defininig path is the parent directory of the file.
|
||||||
<<<<<<< Updated upstream
|
|
||||||
path = llvm::sys::path::parent_path(path);
|
|
||||||
|
|
||||||
// If the defining path is the top-level `.swiftmodule` directory,
|
|
||||||
// take one more step up.
|
|
||||||
if (llvm::sys::path::extension(path) == ".swiftmodule")
|
|
||||||
path = llvm::sys::path::parent_path(path);
|
|
||||||
|
|
||||||
// If the defining path is under `.framework/Modules/` directory,
|
|
||||||
// return the parent path containing the framework.
|
|
||||||
if (llvm::sys::path::filename(path) == "Modules" && llvm::sys::path::extension(llvm::sys::path::parent_path(path)) == ".framework")
|
|
||||||
path = llvm::sys::path::parent_path(llvm::sys::path::parent_path(path));
|
|
||||||
|
|
||||||
return path;
|
|
||||||
=======
|
|
||||||
return llvm::sys::path::parent_path(path).str();
|
return llvm::sys::path::parent_path(path).str();
|
||||||
>>>>>>> Stashed changes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
|
std::optional<std::pair<ModuleDependencyID, std::string>>
|
||||||
|
ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
|
||||||
const ScannerImportStatementInfo &moduleImport,
|
const ScannerImportStatementInfo &moduleImport,
|
||||||
const ModuleDependenciesCache &cache, const SourceLoc &importLoc) {
|
const ModuleDependenciesCache &cache, const SourceLoc &importLoc) {
|
||||||
std::set<ModuleDependencyID> binarySwiftModuleDepIDs =
|
std::set<ModuleDependencyID> binarySwiftModuleDepIDs =
|
||||||
collectBinarySwiftDeps(cache);
|
collectBinarySwiftDeps(cache);
|
||||||
|
|
||||||
|
std::optional<std::pair<ModuleDependencyID, std::string>> result;
|
||||||
for (const auto &binaryDepID : binarySwiftModuleDepIDs) {
|
for (const auto &binaryDepID : binarySwiftModuleDepIDs) {
|
||||||
auto binaryModInfo =
|
auto binaryModInfo =
|
||||||
cache.findKnownDependency(binaryDepID).getAsSwiftBinaryModule();
|
cache.findKnownDependency(binaryDepID).getAsSwiftBinaryModule();
|
||||||
@@ -1772,9 +1777,10 @@ void ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
|
|||||||
// Note: this will permanently mutate this worker with additional search
|
// Note: this will permanently mutate this worker with additional search
|
||||||
// paths. That's fine because we are diagnosing a scan failure here, but
|
// paths. That's fine because we are diagnosing a scan failure here, but
|
||||||
// worth being aware of.
|
// worth being aware of.
|
||||||
withDependencyScanningWorker(
|
result = withDependencyScanningWorker(
|
||||||
[&binaryModInfo, &moduleImport, &cache, &binaryDepID, &importLoc,
|
[&binaryModInfo, &moduleImport, &cache, this,
|
||||||
this](ModuleDependencyScanningWorker *ScanningWorker) {
|
&binaryDepID](ModuleDependencyScanningWorker *ScanningWorker)
|
||||||
|
-> std::optional<std::pair<ModuleDependencyID, std::string>> {
|
||||||
ModuleDependencyVector result;
|
ModuleDependencyVector result;
|
||||||
for (const auto &sp : binaryModInfo->serializedSearchPaths)
|
for (const auto &sp : binaryModInfo->serializedSearchPaths)
|
||||||
ScanningWorker->workerASTContext->addSearchPath(
|
ScanningWorker->workerASTContext->addSearchPath(
|
||||||
@@ -1784,31 +1790,22 @@ void ModuleDependencyScanner::attemptToFindResolvingSerializedSearchPath(
|
|||||||
getModuleImportIdentifier(moduleImport.importIdentifier),
|
getModuleImportIdentifier(moduleImport.importIdentifier),
|
||||||
cache.getModuleOutputPath(), cache.getSDKModuleOutputPath(),
|
cache.getModuleOutputPath(), cache.getSDKModuleOutputPath(),
|
||||||
cache.getScanService().getPrefixMapper());
|
cache.getScanService().getPrefixMapper());
|
||||||
if (!result.empty()) {
|
if (!result.empty())
|
||||||
Diagnostics.diagnose(
|
return std::make_pair(binaryDepID,
|
||||||
importLoc, diag::inherited_search_path_resolves_module,
|
getModuleDefiningPath(result[0].second));
|
||||||
moduleImport.importIdentifier, binaryDepID.ModuleName,
|
|
||||||
getModuleDefiningPath(result[0].second));
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ScanningWorker->scanFilesystemForClangModuleDependency(
|
result = ScanningWorker->scanFilesystemForClangModuleDependency(
|
||||||
getModuleImportIdentifier(moduleImport.importIdentifier),
|
getModuleImportIdentifier(moduleImport.importIdentifier),
|
||||||
cache.getModuleOutputPath(), cache.getSDKModuleOutputPath(), {},
|
cache.getModuleOutputPath(), cache.getSDKModuleOutputPath(), {},
|
||||||
cache.getScanService().getPrefixMapper());
|
cache.getScanService().getPrefixMapper());
|
||||||
<<<<<<< Updated upstream
|
|
||||||
if (!result.empty()) {
|
|
||||||
Diagnostics.diagnose(
|
|
||||||
importLoc, diag::inherited_search_path_resolves_module,
|
|
||||||
moduleImport.importIdentifier, binaryDepID.ModuleName,
|
|
||||||
getModuleDefiningPath(result[0].second));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
=======
|
|
||||||
if (!result.empty())
|
if (!result.empty())
|
||||||
return std::make_pair(binaryDepID,
|
return std::make_pair(binaryDepID,
|
||||||
getModuleDefiningPath(result[0].second));
|
getModuleDefiningPath(result[0].second));
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
>>>>>>> Stashed changes
|
|
||||||
});
|
});
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
// CHECK: remark: Incremental module scan: Re-using serialized module scanning dependency cache from: '{{.*}}cache.moddepcache'.
|
// CHECK: remark: Incremental module scan: Re-using serialized module scanning dependency cache from: '{{.*}}cache.moddepcache'.
|
||||||
// CHECK: remark: Incremental module scan: Dependency info for module 'C' invalidated due to a modified input since last scan: '{{.*}}deps{{/|\\}}C.swiftinterface'.
|
// CHECK: remark: Incremental module scan: Dependency info for module 'C' invalidated due to a modified input since last scan: '{{.*}}deps{{/|\\}}C.swiftinterface'.
|
||||||
// CHECK: remark: Incremental module scan: Dependency info for module 'deps' invalidated due to an out-of-date dependency.
|
// CHECK: remark: Incremental module scan: Dependency info for module 'deps' invalidated due to an out-of-date dependency.
|
||||||
// CHECK: error: Unable to find module dependency: 'C'
|
// CHECK: error: Compilation search paths unable to resolve module dependency: 'C'
|
||||||
|
// 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.
|
||||||
// CHECK: note: a dependency of main module 'deps'
|
// CHECK: note: a dependency of main module 'deps'
|
||||||
// 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.
|
|
||||||
|
|
||||||
//--- moreDeps/C.swiftinterface
|
//--- moreDeps/C.swiftinterface
|
||||||
// swift-interface-format-version: 1.0
|
// swift-interface-format-version: 1.0
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
// 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
|
// 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
|
||||||
// RUN: cat %t/output.txt | %FileCheck %s
|
// RUN: cat %t/output.txt | %FileCheck %s
|
||||||
|
|
||||||
// CHECK: error: Unable to find module dependency: 'C'
|
// CHECK: error: Compilation search paths unable to resolve module dependency: 'C'
|
||||||
|
// 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.
|
||||||
// CHECK: note: a dependency of Swift module 'B': '{{.*}}B.swiftmodule'
|
// CHECK: note: a dependency of Swift module 'B': '{{.*}}B.swiftmodule'
|
||||||
// CHECK: note: a dependency of main module 'deps'
|
// CHECK: note: a dependency of main module 'deps'
|
||||||
// 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.
|
|
||||||
|
|
||||||
//--- moreDeps/C.swiftinterface
|
//--- moreDeps/C.swiftinterface
|
||||||
// swift-interface-format-version: 1.0
|
// swift-interface-format-version: 1.0
|
||||||
|
|||||||
18
userdocs/diagnostics/missing-module-on-known-paths.md
Normal file
18
userdocs/diagnostics/missing-module-on-known-paths.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Missing Module On Known Path From A Dependency Note (`MissingModuleOnKnownPaths`)
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
import Foo
|
||||||
|
```
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
error: Compilation search paths unable to resolve module dependency: 'Bar' [#MissingModuleOnKnownPaths]
|
||||||
|
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.
|
||||||
|
```
|
||||||
|
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.
|
||||||
Reference in New Issue
Block a user