Skip to content

[5.5] Do not build Swift interface files into binary modules when performing a canImport query. #39140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions include/swift/Frontend/ModuleInterfaceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
bool &isFramework, bool &isSystemModule) override;
bool skipBuildingInterface, bool &isFramework,
bool &isSystemModule) override;

std::error_code findModuleFilesInDirectory(
ImportPath::Element ModuleID,
Expand All @@ -148,7 +149,7 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) override;
bool skipBuildingInterface, bool IsFramework) override;

bool canImportModule(ImportPath::Element mID) override;

Expand Down Expand Up @@ -385,7 +386,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) override;
bool skipBuildingInterface, bool IsFramework) override;

bool isCached(StringRef DepPath) override;
public:
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Serialization/ModuleDependencyScanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace swift {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) override;
bool skipBuildingInterface, bool IsFramework) override;

virtual void collectVisibleTopLevelModuleNames(
SmallVectorImpl<Identifier> &names) const override {
Expand Down Expand Up @@ -117,7 +117,7 @@ namespace swift {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) override;
bool skipBuildingInterface, bool IsFramework) override;

static bool classof(const ModuleDependencyScanner *MDS) {
return MDS->getKind() == MDS_placeholder;
Expand Down
8 changes: 4 additions & 4 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
bool &isFramework, bool &isSystemModule);
bool skipBuildingInterface, bool &isFramework, bool &isSystemModule);

/// Attempts to search the provided directory for a loadable serialized
/// .swiftmodule with the provided `ModuleFilename`. Subclasses must
Expand All @@ -98,7 +98,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) = 0;
bool skipBuildingInterface, bool IsFramework) = 0;

std::error_code
openModuleFile(
Expand Down Expand Up @@ -218,7 +218,7 @@ class ImplicitSerializedModuleLoader : public SerializedModuleLoaderBase {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) override;
bool skipBuildingInterface, bool IsFramework) override;

bool maybeDiagnoseTargetMismatch(
SourceLoc sourceLocation,
Expand Down Expand Up @@ -264,7 +264,7 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) override;
bool skipBuildingInterface, bool IsFramework) override;

bool maybeDiagnoseTargetMismatch(
SourceLoc sourceLocation,
Expand Down
16 changes: 13 additions & 3 deletions lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) {
bool skipBuildingInterface, bool IsFramework) {

// If running in OnlySerialized mode, ModuleInterfaceLoader
// should not have been constructed at all.
Expand Down Expand Up @@ -1000,6 +1000,16 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
InPath = PrivateInPath;
}

// If we've been told to skip building interfaces, we are done here and do
// not need to have the module actually built. For example, if we are
// currently answering a `canImport` query, it is enough to have found
// the interface.
if (skipBuildingInterface) {
if (ModuleInterfacePath)
*ModuleInterfacePath = InPath;
return std::error_code();
}

// Create an instance of the Impl to do the heavy lifting.
auto ModuleName = ModuleID.Item.str();
ModuleInterfaceLoaderImpl Impl(
Expand Down Expand Up @@ -1571,7 +1581,7 @@ bool ExplicitSwiftModuleLoader::findModule(ImportPath::Element ModuleID,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool &IsFramework, bool &IsSystemModule) {
bool skipBuildingInterface, bool &IsFramework, bool &IsSystemModule) {
StringRef moduleName = ModuleID.Item.str();
auto it = Impl.ExplicitModuleMap.find(moduleName);
// If no explicit module path is given matches the name, return with an
Expand Down Expand Up @@ -1648,7 +1658,7 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory(
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) {
bool skipBuildingInterface, bool IsFramework) {
llvm_unreachable("Not supported in the Explicit Swift Module Loader.");
return std::make_error_code(std::errc::not_supported);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Serialization/ModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ std::error_code ModuleDependencyScanner::findModuleFilesInDirectory(
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) {
bool skipBuildingInterface, bool IsFramework) {
using namespace llvm::sys;

auto &fs = *Ctx.SourceMgr.getFileSystem();
Expand Down Expand Up @@ -76,7 +76,7 @@ std::error_code PlaceholderSwiftModuleScanner::findModuleFilesInDirectory(
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) {
bool skipBuildingInterface, bool IsFramework) {
StringRef moduleName = ModuleID.Item.str();
auto it = PlaceholderDependencyModuleMap.find(moduleName);
// If no placeholder module stub path is given matches the name, return with an
Expand Down
15 changes: 9 additions & 6 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ std::error_code ImplicitSerializedModuleLoader::findModuleFilesInDirectory(
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) {
bool skipBuildingInterface, bool IsFramework) {
assert(((ModuleBuffer && ModuleDocBuffer) ||
(!ModuleBuffer && !ModuleDocBuffer)) &&
"Module and Module Doc buffer must both be initialized or NULL");
Expand Down Expand Up @@ -514,7 +514,7 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
bool &isFramework, bool &isSystemModule) {
bool skipBuildingInterface, bool &isFramework, bool &isSystemModule) {
SmallString<32> moduleName(moduleID.Item.str());
SerializedModuleBaseName genericBaseName(moduleName);

Expand Down Expand Up @@ -552,6 +552,7 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
moduleInterfacePath,
moduleBuffer, moduleDocBuffer,
moduleSourceInfoBuffer,
skipBuildingInterface,
IsFramework);
if (!result) {
return true;
Expand Down Expand Up @@ -609,7 +610,8 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,

auto result = findModuleFilesInDirectory(
moduleID, absoluteBaseName, moduleInterfacePath,
moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer, isFramework);
moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer,
skipBuildingInterface, isFramework);
if (!result)
return true;
else if (result == std::errc::not_supported)
Expand Down Expand Up @@ -998,9 +1000,10 @@ bool SerializedModuleLoaderBase::canImportModule(
std::unique_ptr<llvm::MemoryBuffer> *unusedModuleSourceInfoBuffer = nullptr;
bool isFramework = false;
bool isSystemModule = false;
bool skipBuildingInterface = true;
return findModule(mID, unusedModuleInterfacePath, unusedModuleBuffer,
unusedModuleDocBuffer, unusedModuleSourceInfoBuffer,
isFramework, isSystemModule);
skipBuildingInterface, isFramework, isSystemModule);
}

bool MemoryBufferSerializedModuleLoader::canImportModule(
Expand Down Expand Up @@ -1028,7 +1031,7 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
// Look on disk.
if (!findModule(moduleID, &moduleInterfacePath, &moduleInputBuffer,
&moduleDocInputBuffer, &moduleSourceInfoInputBuffer,
isFramework, isSystemModule)) {
/* skipBuildingInterface */ false, isFramework, isSystemModule)) {
return nullptr;
}

Expand Down Expand Up @@ -1142,7 +1145,7 @@ std::error_code MemoryBufferSerializedModuleLoader::findModuleFilesInDirectory(
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool IsFramework) {
bool skipBuildingInterface, bool IsFramework) {
// This is a soft error instead of an llvm_unreachable because this API is
// primarily used by LLDB which makes it more likely that unwitting changes to
// the Swift compiler accidentally break the contract.
Expand Down
4 changes: 4 additions & 0 deletions test/ScanDependencies/Inputs/Swift/Foo.swiftinterface
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// swift-interface-format-version: 1.0
// swift-module-flags: -module-name Foo
import Swift

9 changes: 9 additions & 0 deletions test/ScanDependencies/can_import_no_build.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %target-swift-frontend -c -primary-file %s -Rmodule-interface-rebuild -I %S/Inputs/Swift/

#if canImport(Foo)
print("Can indeed import Foo!")
#else
print("Cannot import Foo!")
#endif

// CHECK-NOT: rebuilding module 'Foo' from interface
3 changes: 2 additions & 1 deletion unittests/FrontendTool/ModuleLoadingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ class ModuleInterfaceLoaderTest : public testing::Test {
loader->findModuleFilesInDirectory({moduleName, SourceLoc()},
SerializedModuleBaseName(tempDir, SerializedModuleBaseName("Library")),
/*ModuleInterfacePath*/nullptr,
&moduleBuffer, &moduleDocBuffer, &moduleSourceInfoBuffer, /*IsFramework*/false);
&moduleBuffer, &moduleDocBuffer, &moduleSourceInfoBuffer,
/*skipBuildingInterface*/ false, /*IsFramework*/false);
ASSERT_FALSE(error);
ASSERT_FALSE(diags.hadAnyError());

Expand Down