Skip to content

Commit aa71036

Browse files
committed
Do not build Swift interface files into binary modules when performing a canImport query.
We should hold off actually building the binary module file until it is imported. `canImport` queries can happen, for example, during dependency scanning, when we do not wish to have the scanner tool execute any module builds. Resolves rdar://82603098
1 parent 43aaf29 commit aa71036

File tree

9 files changed

+49
-21
lines changed

9 files changed

+49
-21
lines changed

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
139139
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
140140
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
141141
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
142-
bool &isFramework, bool &isSystemModule) override;
142+
bool skipBuildingInterface, bool &isFramework,
143+
bool &isSystemModule) override;
143144

144145
std::error_code findModuleFilesInDirectory(
145146
ImportPath::Element ModuleID,
@@ -148,7 +149,7 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
148149
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
149150
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
150151
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
151-
bool IsFramework) override;
152+
bool skipBuildingInterface, bool IsFramework) override;
152153

153154
bool canImportModule(ImportPath::Element mID) override;
154155

@@ -385,7 +386,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
385386
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
386387
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
387388
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
388-
bool IsFramework) override;
389+
bool skipBuildingInterface, bool IsFramework) override;
389390

390391
bool isCached(StringRef DepPath) override;
391392
public:

include/swift/Serialization/ModuleDependencyScanner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ namespace swift {
5555
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
5656
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
5757
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
58-
bool IsFramework) override;
58+
bool skipBuildingInterface, bool IsFramework) override;
5959

6060
virtual void collectVisibleTopLevelModuleNames(
6161
SmallVectorImpl<Identifier> &names) const override {
@@ -117,7 +117,7 @@ namespace swift {
117117
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
118118
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
119119
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
120-
bool IsFramework) override;
120+
bool skipBuildingInterface, bool IsFramework) override;
121121

122122
static bool classof(const ModuleDependencyScanner *MDS) {
123123
return MDS->getKind() == MDS_placeholder;

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
7777
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
7878
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
7979
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
80-
bool &isFramework, bool &isSystemModule);
80+
bool skipBuildingInterface, bool &isFramework, bool &isSystemModule);
8181

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

103103
std::error_code
104104
openModuleFile(
@@ -218,7 +218,7 @@ class ImplicitSerializedModuleLoader : public SerializedModuleLoaderBase {
218218
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
219219
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
220220
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
221-
bool IsFramework) override;
221+
bool skipBuildingInterface, bool IsFramework) override;
222222

223223
bool maybeDiagnoseTargetMismatch(
224224
SourceLoc sourceLocation,
@@ -264,7 +264,7 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
264264
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
265265
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
266266
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
267-
bool IsFramework) override;
267+
bool skipBuildingInterface, bool IsFramework) override;
268268

269269
bool maybeDiagnoseTargetMismatch(
270270
SourceLoc sourceLocation,

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
972972
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
973973
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
974974
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
975-
bool IsFramework) {
975+
bool skipBuildingInterface, bool IsFramework) {
976976

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

1003+
// If we've been told to skip building interfaces, we are done here and do
1004+
// not need to have the module actually built. For example, if we are
1005+
// currently answering a `canImport` query, it is enough to have found
1006+
// the interface.
1007+
if (skipBuildingInterface) {
1008+
if (ModuleInterfacePath)
1009+
*ModuleInterfacePath = InPath;
1010+
return std::error_code();
1011+
}
1012+
10031013
// Create an instance of the Impl to do the heavy lifting.
10041014
auto ModuleName = ModuleID.Item.str();
10051015
ModuleInterfaceLoaderImpl Impl(
@@ -1571,7 +1581,7 @@ bool ExplicitSwiftModuleLoader::findModule(ImportPath::Element ModuleID,
15711581
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
15721582
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
15731583
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
1574-
bool &IsFramework, bool &IsSystemModule) {
1584+
bool skipBuildingInterface, bool &IsFramework, bool &IsSystemModule) {
15751585
StringRef moduleName = ModuleID.Item.str();
15761586
auto it = Impl.ExplicitModuleMap.find(moduleName);
15771587
// If no explicit module path is given matches the name, return with an
@@ -1648,7 +1658,7 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory(
16481658
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
16491659
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
16501660
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
1651-
bool IsFramework) {
1661+
bool skipBuildingInterface, bool IsFramework) {
16521662
llvm_unreachable("Not supported in the Explicit Swift Module Loader.");
16531663
return std::make_error_code(std::errc::not_supported);
16541664
}

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ std::error_code ModuleDependencyScanner::findModuleFilesInDirectory(
3232
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
3333
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
3434
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
35-
bool IsFramework) {
35+
bool skipBuildingInterface, bool IsFramework) {
3636
using namespace llvm::sys;
3737

3838
auto &fs = *Ctx.SourceMgr.getFileSystem();
@@ -76,7 +76,7 @@ std::error_code PlaceholderSwiftModuleScanner::findModuleFilesInDirectory(
7676
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
7777
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
7878
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
79-
bool IsFramework) {
79+
bool skipBuildingInterface, bool IsFramework) {
8080
StringRef moduleName = ModuleID.Item.str();
8181
auto it = PlaceholderDependencyModuleMap.find(moduleName);
8282
// If no placeholder module stub path is given matches the name, return with an

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ std::error_code ImplicitSerializedModuleLoader::findModuleFilesInDirectory(
421421
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
422422
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
423423
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
424-
bool IsFramework) {
424+
bool skipBuildingInterface, bool IsFramework) {
425425
assert(((ModuleBuffer && ModuleDocBuffer) ||
426426
(!ModuleBuffer && !ModuleDocBuffer)) &&
427427
"Module and Module Doc buffer must both be initialized or NULL");
@@ -514,7 +514,7 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
514514
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
515515
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
516516
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
517-
bool &isFramework, bool &isSystemModule) {
517+
bool skipBuildingInterface, bool &isFramework, bool &isSystemModule) {
518518
SmallString<32> moduleName(moduleID.Item.str());
519519
SerializedModuleBaseName genericBaseName(moduleName);
520520

@@ -552,6 +552,7 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
552552
moduleInterfacePath,
553553
moduleBuffer, moduleDocBuffer,
554554
moduleSourceInfoBuffer,
555+
skipBuildingInterface,
555556
IsFramework);
556557
if (!result) {
557558
return true;
@@ -609,7 +610,8 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
609610

610611
auto result = findModuleFilesInDirectory(
611612
moduleID, absoluteBaseName, moduleInterfacePath,
612-
moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer, isFramework);
613+
moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer,
614+
skipBuildingInterface, isFramework);
613615
if (!result)
614616
return true;
615617
else if (result == std::errc::not_supported)
@@ -998,9 +1000,10 @@ bool SerializedModuleLoaderBase::canImportModule(
9981000
std::unique_ptr<llvm::MemoryBuffer> *unusedModuleSourceInfoBuffer = nullptr;
9991001
bool isFramework = false;
10001002
bool isSystemModule = false;
1003+
bool skipBuildingInterface = true;
10011004
return findModule(mID, unusedModuleInterfacePath, unusedModuleBuffer,
10021005
unusedModuleDocBuffer, unusedModuleSourceInfoBuffer,
1003-
isFramework, isSystemModule);
1006+
skipBuildingInterface, isFramework, isSystemModule);
10041007
}
10051008

10061009
bool MemoryBufferSerializedModuleLoader::canImportModule(
@@ -1028,7 +1031,7 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
10281031
// Look on disk.
10291032
if (!findModule(moduleID, &moduleInterfacePath, &moduleInputBuffer,
10301033
&moduleDocInputBuffer, &moduleSourceInfoInputBuffer,
1031-
isFramework, isSystemModule)) {
1034+
/* skipBuildingInterface */ false, isFramework, isSystemModule)) {
10321035
return nullptr;
10331036
}
10341037

@@ -1142,7 +1145,7 @@ std::error_code MemoryBufferSerializedModuleLoader::findModuleFilesInDirectory(
11421145
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
11431146
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
11441147
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
1145-
bool IsFramework) {
1148+
bool skipBuildingInterface, bool IsFramework) {
11461149
// This is a soft error instead of an llvm_unreachable because this API is
11471150
// primarily used by LLDB which makes it more likely that unwitting changes to
11481151
// the Swift compiler accidentally break the contract.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name Foo
3+
import Swift
4+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -c -primary-file %s -Rmodule-interface-rebuild -I %S/Inputs/Swift/
2+
3+
#if canImport(Foo)
4+
print("Can indeed import Foo!")
5+
#else
6+
print("Cannot import Foo!")
7+
#endif
8+
9+
// CHECK-NOT: rebuilding module 'Foo' from interface

unittests/FrontendTool/ModuleLoadingTests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ class ModuleInterfaceLoaderTest : public testing::Test {
128128
loader->findModuleFilesInDirectory({moduleName, SourceLoc()},
129129
SerializedModuleBaseName(tempDir, SerializedModuleBaseName("Library")),
130130
/*ModuleInterfacePath*/nullptr,
131-
&moduleBuffer, &moduleDocBuffer, &moduleSourceInfoBuffer, /*IsFramework*/false);
131+
&moduleBuffer, &moduleDocBuffer, &moduleSourceInfoBuffer,
132+
/*skipBuildingInterface*/ false, /*IsFramework*/false);
132133
ASSERT_FALSE(error);
133134
ASSERT_FALSE(diags.hadAnyError());
134135

0 commit comments

Comments
 (0)