Skip to content

Commit affbe34

Browse files
committed
[Dependency Scanning] Pull optional dependencies from the adjacent binary module for direct interface dependencies
For a `@Testable` import in program source, if a Swift interface dependency is discovered, and has an adjacent binary `.swiftmodule`, open up the module, and pull in its optional dependencies. If an optional dependency cannot be resolved on the filesystem, fail silently without raising a diagnostic.
1 parent dc2166c commit affbe34

17 files changed

+140
-48
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,7 @@ class ASTContext final {
10211021
ModuleDependenciesCache &cache,
10221022
InterfaceSubContextDelegate &delegate,
10231023
bool optionalDependencyLookup = false,
1024+
bool isTestableImport = false,
10241025
llvm::Optional<std::pair<std::string, swift::ModuleDependencyKind>> dependencyOf = None);
10251026

10261027
/// Retrieve the module dependencies for the Clang module with the given name.

include/swift/AST/ModuleLoader.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ class ModuleLoader {
241241
/// If a non-null \p versionInfo is provided, the module version will be
242242
/// parsed and populated.
243243
virtual bool canImportModule(ImportPath::Module named,
244-
ModuleVersionInfo *versionInfo) = 0;
244+
ModuleVersionInfo *versionInfo,
245+
bool isTestableImport = false) = 0;
245246

246247
/// Import a module with the given module path.
247248
///
@@ -324,7 +325,8 @@ class ModuleLoader {
324325
virtual Optional<const ModuleDependencyInfo*> getModuleDependencies(
325326
StringRef moduleName,
326327
ModuleDependenciesCache &cache,
327-
InterfaceSubContextDelegate &delegate) = 0;
328+
InterfaceSubContextDelegate &delegate,
329+
bool isTestableImport = false) = 0;
328330
};
329331

330332
} // namespace swift

include/swift/ClangImporter/ClangImporter.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ class ClangImporter final : public ClangModuleLoader {
212212
/// If a non-null \p versionInfo is provided, the module version will be
213213
/// parsed and populated.
214214
virtual bool canImportModule(ImportPath::Module named,
215-
ModuleVersionInfo *versionInfo) override;
215+
ModuleVersionInfo *versionInfo,
216+
bool isTestableImport = false) override;
216217

217218
/// Import a module with the given module path.
218219
///
@@ -427,7 +428,8 @@ class ClangImporter final : public ClangModuleLoader {
427428

428429
Optional<const ModuleDependencyInfo*> getModuleDependencies(
429430
StringRef moduleName, ModuleDependenciesCache &cache,
430-
InterfaceSubContextDelegate &delegate) override;
431+
InterfaceSubContextDelegate &delegate,
432+
bool isTestableImport = false) override;
431433

432434
/// Add dependency information for the bridging header.
433435
///

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
142142
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
143143
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
144144
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
145-
bool skipBuildingInterface, bool &isFramework,
146-
bool &isSystemModule) override;
145+
bool skipBuildingInterface, bool isTestableDependencyLookup,
146+
bool &isFramework, bool &isSystemModule) override;
147147

148148
std::error_code findModuleFilesInDirectory(
149149
ImportPath::Element ModuleID, const SerializedModuleBaseName &BaseName,
@@ -152,10 +152,12 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
152152
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
153153
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
154154
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
155-
bool skipBuildingInterface, bool IsFramework) override;
155+
bool SkipBuildingInterface, bool IsFramework,
156+
bool IsTestableDependencyLookup = false) override;
156157

157158
bool canImportModule(ImportPath::Module named,
158-
ModuleVersionInfo *versionInfo) override;
159+
ModuleVersionInfo *versionInfo,
160+
bool isTestableDependencyLookup = false) override;
159161

160162
bool isCached(StringRef DepPath) override { return false; };
161163

@@ -476,7 +478,8 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
476478
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
477479
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
478480
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
479-
bool skipBuildingInterface, bool IsFramework) override;
481+
bool SkipBuildingInterface, bool IsFramework,
482+
bool IsTestableDependencyLookup = false) override;
480483

481484
bool isCached(StringRef DepPath) override;
482485
public:

include/swift/Sema/SourceLoader.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class SourceLoader : public ModuleLoader {
6060
/// If a non-null \p versionInfo is provided, the module version will be
6161
/// parsed and populated.
6262
virtual bool canImportModule(ImportPath::Module named,
63-
ModuleVersionInfo *versionInfo) override;
63+
ModuleVersionInfo *versionInfo,
64+
bool isTestableDependencyLookup = false) override;
6465

6566
/// Import a module with the given module path.
6667
///
@@ -98,7 +99,8 @@ class SourceLoader : public ModuleLoader {
9899

99100
Optional<const ModuleDependencyInfo*>
100101
getModuleDependencies(StringRef moduleName, ModuleDependenciesCache &cache,
101-
InterfaceSubContextDelegate &delegate) override;
102+
InterfaceSubContextDelegate &delegate,
103+
bool isTestableImport) override;
102104
};
103105
}
104106

include/swift/Serialization/ModuleDependencyScanner.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ namespace swift {
3434

3535
/// Scan the given interface file to determine dependencies.
3636
llvm::ErrorOr<ModuleDependencyInfo> scanInterfaceFile(
37-
Twine moduleInterfacePath, bool isFramework);
37+
Twine moduleInterfacePath, bool isFramework,
38+
bool isTestableImport);
3839

3940
InterfaceSubContextDelegate &astDelegate;
4041

@@ -61,7 +62,8 @@ namespace swift {
6162
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
6263
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
6364
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
64-
bool skipBuildingInterface, bool IsFramework) override;
65+
bool SkipBuildingInterface, bool IsFramework,
66+
bool IsTestableDependencyLookup) override;
6567

6668
virtual void collectVisibleTopLevelModuleNames(
6769
SmallVectorImpl<Identifier> &names) const override {
@@ -125,8 +127,8 @@ namespace swift {
125127
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
126128
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
127129
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
128-
bool skipBuildingInterface, bool &isFramework,
129-
bool &isSystemModule) override;
130+
bool skipBuildingInterface, bool isTestableDependencyLookup,
131+
bool &isFramework, bool &isSystemModule) override;
130132

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

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
8686
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
8787
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
8888
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
89-
bool skipBuildingInterface, bool &isFramework, bool &isSystemModule);
89+
bool skipBuildingInterface, bool isTestableDependencyLookup,
90+
bool &isFramework, bool &isSystemModule);
9091

9192
/// Attempts to search the provided directory for a loadable serialized
9293
/// .swiftmodule with the provided `ModuleFilename`. Subclasses must
@@ -107,7 +108,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
107108
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
108109
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
109110
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
110-
bool skipBuildingInterface, bool IsFramework) = 0;
111+
bool SkipBuildingInterface, bool IsFramework,
112+
bool isTestableDependencyLookup = false) = 0;
111113

112114
std::error_code
113115
openModuleFile(
@@ -191,7 +193,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
191193
/// If a non-null \p versionInfo is provided, the module version will be
192194
/// parsed and populated.
193195
virtual bool canImportModule(ImportPath::Module named,
194-
ModuleVersionInfo *versionInfo) override;
196+
ModuleVersionInfo *versionInfo,
197+
bool isTestableDependencyLookup = false) override;
195198

196199
/// Import a module with the given module path.
197200
///
@@ -226,7 +229,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
226229

227230
virtual Optional<const ModuleDependencyInfo*> getModuleDependencies(
228231
StringRef moduleName, ModuleDependenciesCache &cache,
229-
InterfaceSubContextDelegate &delegate) override;
232+
InterfaceSubContextDelegate &delegate,
233+
bool isTestableImport) override;
230234
};
231235

232236
/// Imports serialized Swift modules into an ASTContext.
@@ -244,7 +248,8 @@ class ImplicitSerializedModuleLoader : public SerializedModuleLoaderBase {
244248
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
245249
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
246250
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
247-
bool skipBuildingInterface, bool IsFramework) override;
251+
bool SkipBuildingInterface, bool IsFramework,
252+
bool isTestableDependencyLookup = false) override;
248253

249254
bool maybeDiagnoseTargetMismatch(
250255
SourceLoc sourceLocation,
@@ -298,7 +303,8 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
298303
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
299304
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
300305
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
301-
bool skipBuildingInterface, bool IsFramework) override;
306+
bool SkipBuildingInterface, bool IsFramework,
307+
bool IsTestableDependencyLookup = false) override;
302308

303309
bool maybeDiagnoseTargetMismatch(
304310
SourceLoc sourceLocation,
@@ -310,7 +316,8 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
310316
virtual ~MemoryBufferSerializedModuleLoader();
311317

312318
bool canImportModule(ImportPath::Module named,
313-
ModuleVersionInfo *versionInfo) override;
319+
ModuleVersionInfo *versionInfo,
320+
bool isTestableDependencyLookup = false) override;
314321

315322
ModuleDecl *
316323
loadModule(SourceLoc importLoc,

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,7 @@ Optional<const ModuleDependencyInfo*> ASTContext::getModuleDependencies(
20102010
StringRef moduleName, ModuleDependenciesCache &cache,
20112011
InterfaceSubContextDelegate &delegate,
20122012
bool optionalDependencyLookup,
2013+
bool isTestableImport,
20132014
llvm::Optional<ModuleDependencyID> dependencyOf) {
20142015
// Retrieve the dependencies for this module.
20152016
// Check whether we've cached this result.
@@ -2031,7 +2032,8 @@ Optional<const ModuleDependencyInfo*> ASTContext::getModuleDependencies(
20312032

20322033
for (auto &loader : getImpl().ModuleLoaders) {
20332034
if (auto dependencies =
2034-
loader->getModuleDependencies(moduleName, cache, delegate))
2035+
loader->getModuleDependencies(moduleName, cache, delegate,
2036+
isTestableImport))
20352037
return dependencies;
20362038
}
20372039

lib/AST/ModuleDependencies.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ void ModuleDependencyInfo::addModuleImport(
127127
auto realPath = importDecl->getRealModulePath(scratch);
128128
addModuleImport(realPath, &alreadyAddedModules);
129129

130+
// Additionally, keep track of which dependencies of a Source
131+
// module are `@Testable`.
130132
if (getKind() == swift::ModuleDependencyKind::SwiftSource &&
131133
importDecl->isTestable())
132134
addTestableImport(realPath);
@@ -140,9 +142,8 @@ void ModuleDependencyInfo::addModuleImport(
140142
case swift::ModuleDependencyKind::SwiftInterface: {
141143
// If the storage is for an interface file, the only source file we
142144
// should see is that interface file.
143-
auto swiftInterfaceStorage =
144-
cast<SwiftInterfaceModuleDependenciesStorage>(storage.get());
145-
assert(fileName == swiftInterfaceStorage->swiftInterfaceFile);
145+
assert(fileName ==
146+
cast<SwiftInterfaceModuleDependenciesStorage>(storage.get())->swiftInterfaceFile);
146147
break;
147148
}
148149
case swift::ModuleDependencyKind::SwiftSource: {

lib/ClangImporter/ClangImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,8 @@ static std::string getScalaNodeText(llvm::yaml::Node *N) {
18551855
}
18561856

18571857
bool ClangImporter::canImportModule(ImportPath::Module modulePath,
1858-
ModuleVersionInfo *versionInfo) {
1858+
ModuleVersionInfo *versionInfo,
1859+
bool isTestableDependencyLookup) {
18591860
// Look up the top-level module to see if it exists.
18601861
auto &clangHeaderSearch = Impl.getClangPreprocessor().getHeaderSearchInfo();
18611862
auto topModule = modulePath.front();

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ void ClangImporter::recordModuleDependencies(
202202

203203
Optional<const ModuleDependencyInfo*> ClangImporter::getModuleDependencies(
204204
StringRef moduleName, ModuleDependenciesCache &cache,
205-
InterfaceSubContextDelegate &delegate) {
205+
InterfaceSubContextDelegate &delegate, bool isTestableImport) {
206206
auto &ctx = Impl.SwiftContext;
207207
// Determine the command-line arguments for dependency scanning.
208208
std::vector<std::string> commandLineArgs =

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI
327327
for (auto dependsOn : knownDependencies->getModuleImports()) {
328328
// Figure out what kind of module we need.
329329
bool onlyClangModule = !isSwift || moduleID.first == dependsOn;
330+
bool isTestable = knownDependencies->isTestableImport(dependsOn);
331+
330332
if (onlyClangModule) {
331333
if (auto found =
332334
ctx.getClangModuleDependencies(dependsOn, cache, ASTDelegate))
@@ -335,6 +337,7 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI
335337
if (auto found =
336338
ctx.getModuleDependencies(dependsOn, cache, ASTDelegate,
337339
/* optionalDependencyLookup */ false,
340+
isTestable,
338341
moduleID))
339342
result.insert({dependsOn, found.value()->getKind()});
340343
}
@@ -347,6 +350,7 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI
347350
if (auto found =
348351
ctx.getModuleDependencies(optionallyDependsOn, cache, ASTDelegate,
349352
/* optionalDependencyLookup */ true,
353+
/* isTestableDependency */ false,
350354
moduleID))
351355
result.insert({optionallyDependsOn, found.value()->getKind()});
352356
}

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
11461146
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
11471147
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
11481148
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
1149-
bool skipBuildingInterface, bool IsFramework) {
1149+
bool skipBuildingInterface, bool IsFramework,
1150+
bool isTestableImport) {
11501151

11511152
// If running in OnlySerialized mode, ModuleInterfaceLoader
11521153
// should not have been constructed at all.
@@ -1980,7 +1981,8 @@ bool ExplicitSwiftModuleLoader::findModule(
19801981
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
19811982
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
19821983
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
1983-
bool skipBuildingInterface, bool &IsFramework, bool &IsSystemModule) {
1984+
bool skipBuildingInterface, bool isTestableDependencyLookup,
1985+
bool &IsFramework, bool &IsSystemModule) {
19841986
// Find a module with an actual, physical name on disk, in case
19851987
// -module-alias is used (otherwise same).
19861988
//
@@ -2058,13 +2060,15 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory(
20582060
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
20592061
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
20602062
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
2061-
bool skipBuildingInterface, bool IsFramework) {
2063+
bool skipBuildingInterface, bool IsFramework,
2064+
bool IsTestableDependencyLookup) {
20622065
llvm_unreachable("Not supported in the Explicit Swift Module Loader.");
20632066
return std::make_error_code(std::errc::not_supported);
20642067
}
20652068

20662069
bool ExplicitSwiftModuleLoader::canImportModule(
2067-
ImportPath::Module path, ModuleVersionInfo *versionInfo) {
2070+
ImportPath::Module path, ModuleVersionInfo *versionInfo,
2071+
bool isTestableDependencyLookup) {
20682072
// FIXME: Swift submodules?
20692073
if (path.hasSubmodule())
20702074
return false;

lib/Sema/SourceLoader.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ void SourceLoader::collectVisibleTopLevelModuleNames(
7171
}
7272

7373
bool SourceLoader::canImportModule(ImportPath::Module path,
74-
ModuleVersionInfo *versionInfo) {
74+
ModuleVersionInfo *versionInfo,
75+
bool isTestableDependencyLookup) {
7576
// FIXME: Swift submodules?
7677
if (path.hasSubmodule())
7778
return false;
@@ -155,7 +156,8 @@ void SourceLoader::loadExtensions(NominalTypeDecl *nominal,
155156
Optional<const ModuleDependencyInfo*>
156157
SourceLoader::getModuleDependencies(StringRef moduleName,
157158
ModuleDependenciesCache &cache,
158-
InterfaceSubContextDelegate &delegate) {
159+
InterfaceSubContextDelegate &delegate,
160+
bool isTestableImport) {
159161
// FIXME: Implement?
160162
return None;
161163
}

0 commit comments

Comments
 (0)