Skip to content

Commit 9b2a436

Browse files
[ScanDependency] Do not use public/private swiftinterface in the same package
When scanning finds a dependency in the same package, do not load public/private swiftinterface since they do not have the package level decl to compile the current module. Always prefer package module (if enabled), or use binary module. This also does some clean up to sync up the code path between implicit and explicit module finding path. rdar://122356964
1 parent 6636471 commit 9b2a436

File tree

5 files changed

+74
-73
lines changed

5 files changed

+74
-73
lines changed

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ struct SerializedModuleBaseName {
6868
std::optional<std::string> findInterfacePath(llvm::vfs::FileSystem &fs,
6969
ASTContext &ctx) const;
7070

71+
/// Returns the package-name of the interface file.
72+
std::optional<std::string>
73+
getPackageNameFromInterfacePath(StringRef interfacePath,
74+
llvm::vfs::FileSystem &fs) const;
75+
7176
/// Returns the .package.swiftinterface path if its package-name also applies to
7277
/// the the importing module. Returns an empty optional otherwise.
7378
std::optional<std::string>

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,8 +1244,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
12441244

12451245
// First check to see if the .swiftinterface exists at all. Bail if not.
12461246
auto &fs = *Ctx.SourceMgr.getFileSystem();
1247-
std::string InPath = BaseName.findInterfacePath(fs, Ctx).value_or("");
1248-
if (InPath.empty()) {
1247+
auto InPath = BaseName.findInterfacePath(fs, Ctx);
1248+
if (!InPath) {
12491249
if (fs.exists(ModPath)) {
12501250
LLVM_DEBUG(llvm::dbgs()
12511251
<< "No .swiftinterface file found adjacent to module file "
@@ -1256,22 +1256,22 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
12561256
}
12571257

12581258
if (ModuleInterfaceSourcePath)
1259-
ModuleInterfaceSourcePath->assign(InPath.begin(), InPath.end());
1259+
ModuleInterfaceSourcePath->assign(InPath->begin(), InPath->end());
12601260

12611261
// If we've been told to skip building interfaces, we are done here and do
12621262
// not need to have the module actually built. For example, if we are
12631263
// currently answering a `canImport` query, it is enough to have found
12641264
// the interface.
12651265
if (skipBuildingInterface) {
12661266
if (ModuleInterfacePath)
1267-
ModuleInterfacePath->assign(InPath.begin(), InPath.end());
1267+
ModuleInterfacePath->assign(InPath->begin(), InPath->end());
12681268
return std::error_code();
12691269
}
12701270

12711271
// Create an instance of the Impl to do the heavy lifting.
12721272
auto ModuleName = ModuleID.Item.str();
12731273
ModuleInterfaceLoaderImpl Impl(
1274-
Ctx, ModPath, InPath, ModuleName, InterfaceChecker.CacheDir,
1274+
Ctx, ModPath, *InPath, ModuleName, InterfaceChecker.CacheDir,
12751275
InterfaceChecker.PrebuiltCacheDir, InterfaceChecker.BackupInterfaceDir,
12761276
ModuleID.Loc, InterfaceChecker.Opts,
12771277
InterfaceChecker.RequiresOSSAModules,
@@ -1290,7 +1290,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
12901290
if (ModuleBuffer) {
12911291
*ModuleBuffer = std::move(*ModuleBufferOrErr);
12921292
if (ModuleInterfacePath)
1293-
ModuleInterfacePath->assign(InPath.begin(), InPath.end());
1293+
ModuleInterfacePath->assign(InPath->begin(), InPath->end());
12941294
}
12951295

12961296
// Open .swiftsourceinfo file if it's present.

lib/Serialization/ScanningLoaders.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ std::error_code SwiftModuleScanner::findModuleFilesInDirectory(
5050
auto &fs = *Ctx.SourceMgr.getFileSystem();
5151

5252
auto ModPath = BaseName.getName(file_types::TY_SwiftModuleFile);
53-
auto InPath = BaseName.getName(file_types::TY_SwiftModuleInterfaceFile);
53+
auto InPath = BaseName.findInterfacePath(fs, Ctx);
5454

55-
if (LoadMode == ModuleLoadingMode::OnlySerialized || !fs.exists(InPath)) {
55+
if (LoadMode == ModuleLoadingMode::OnlySerialized || !InPath) {
5656
if (fs.exists(ModPath)) {
5757
// The module file will be loaded directly.
5858
auto dependencies = scanModuleFile(ModPath, IsFramework);
@@ -61,26 +61,12 @@ std::error_code SwiftModuleScanner::findModuleFilesInDirectory(
6161
return std::error_code();
6262
}
6363
return dependencies.getError();
64-
} else {
65-
return std::make_error_code(std::errc::no_such_file_or_directory);
6664
}
65+
return std::make_error_code(std::errc::no_such_file_or_directory);
6766
}
68-
assert(fs.exists(InPath));
67+
assert(InPath);
6968

70-
// Use package.swiftinterface if it exists and its package-name applies to
71-
// the importer module.
72-
auto PkgInPath = BaseName.getPackageInterfacePathIfInSamePackage(fs, Ctx).value_or("");
73-
if (!PkgInPath.empty() && fs.exists(PkgInPath)) {
74-
InPath = PkgInPath;
75-
} else {
76-
// If not in package, use the private interface file if exits.
77-
auto PrivateInPath =
78-
BaseName.getName(file_types::TY_PrivateSwiftModuleInterfaceFile);
79-
if (fs.exists(PrivateInPath)) {
80-
InPath = PrivateInPath;
81-
}
82-
}
83-
auto dependencies = scanInterfaceFile(InPath, IsFramework);
69+
auto dependencies = scanInterfaceFile(*InPath, IsFramework);
8470
if (dependencies) {
8571
this->dependencies = std::move(dependencies.get());
8672
return std::error_code();

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -604,35 +604,43 @@ std::optional<std::string>
604604
SerializedModuleBaseName::getPackageInterfacePathIfInSamePackage(
605605
llvm::vfs::FileSystem &fs, ASTContext &ctx) const {
606606
if (!ctx.LangOpts.EnablePackageInterfaceLoad)
607-
return {};
607+
return std::nullopt;
608608

609609
std::string packagePath{
610-
getName(file_types::TY_PackageSwiftModuleInterfaceFile)};
610+
getName(file_types::TY_PackageSwiftModuleInterfaceFile)};
611611

612612
if (fs.exists(packagePath)) {
613613
// Read the interface file and extract its package-name argument value
614-
StringRef result;
615-
if (auto packageFile = llvm::MemoryBuffer::getFile(packagePath)) {
616-
llvm::BumpPtrAllocator alloc;
617-
llvm::StringSaver argSaver(alloc);
618-
SmallVector<const char*, 8> args;
619-
(void)extractCompilerFlagsFromInterface(packagePath,
620-
(*packageFile)->getBuffer(), argSaver, args);
621-
for (unsigned I = 0, N = args.size(); I + 1 < N; I++) {
622-
StringRef current(args[I]), next(args[I + 1]);
623-
if (current == "-package-name") {
624-
// Instead of `break` here, continue to get the last value in case of dupes,
625-
// to be consistent with the default parsing logic.
626-
result = next;
627-
}
614+
if (auto packageName = getPackageNameFromInterfacePath(packagePath, fs)) {
615+
// Return the .package.swiftinterface path if the package name applies to
616+
// the importer module.
617+
if (*packageName == ctx.LangOpts.PackageName)
618+
return packagePath;
619+
}
620+
}
621+
return std::nullopt;
622+
}
623+
624+
std::optional<std::string>
625+
SerializedModuleBaseName::getPackageNameFromInterfacePath(
626+
StringRef interfacePath, llvm::vfs::FileSystem &fs) const {
627+
std::optional<std::string> result;
628+
if (auto interfaceFile = fs.getBufferForFile(interfacePath)) {
629+
llvm::BumpPtrAllocator alloc;
630+
llvm::StringSaver argSaver(alloc);
631+
SmallVector<const char *, 8> args;
632+
(void)extractCompilerFlagsFromInterface(
633+
interfacePath, (*interfaceFile)->getBuffer(), argSaver, args);
634+
for (unsigned I = 0, N = args.size(); I + 1 < N; I++) {
635+
StringRef current(args[I]), next(args[I + 1]);
636+
if (current == "-package-name") {
637+
// Instead of `break` here, continue to get the last value in case of
638+
// dupes, to be consistent with the default parsing logic.
639+
result = next;
628640
}
629641
}
630-
// Return the .package.swiftinterface path if the package name applies to
631-
// the importer module.
632-
if (!result.empty() && result == ctx.LangOpts.PackageName)
633-
return packagePath;
634642
}
635-
return {};
643+
return result;
636644
}
637645

638646
std::optional<std::string>
@@ -642,16 +650,15 @@ SerializedModuleBaseName::findInterfacePath(llvm::vfs::FileSystem &fs,
642650
// Ensure the public swiftinterface already exists, otherwise bail early
643651
// as it's considered the module doesn't exist.
644652
if (!fs.exists(interfacePath))
645-
return {};
653+
return std::nullopt;
646654

647-
// Check if a package interface exists and if the package name applies to
648-
// the importer module.
649-
auto pkgPath = getPackageInterfacePathIfInSamePackage(fs, ctx).value_or("");
650-
if (!pkgPath.empty() && fs.exists(pkgPath))
651-
return pkgPath;
655+
// If in the same package, try return the package interface path.
656+
if (auto packageName = getPackageNameFromInterfacePath(interfacePath, fs)) {
657+
if (*packageName == ctx.LangOpts.PackageName)
658+
return getPackageInterfacePathIfInSamePackage(fs, ctx);
659+
}
652660

653-
// If above fails, use the existing logic as fallback.
654-
// If present, use the private interface instead of the public one.
661+
// Otherwise, use the private interface instead of the public one.
655662
std::string privatePath{
656663
getName(file_types::TY_PrivateSwiftModuleInterfaceFile)};
657664
if (fs.exists(privatePath))
@@ -704,35 +711,33 @@ bool SerializedModuleLoaderBase::findModule(
704711
std::optional<SerializedModuleBaseName> firstAbsoluteBaseName;
705712

706713
for (const auto &targetSpecificBaseName : targetSpecificBaseNames) {
707-
SerializedModuleBaseName
708-
absoluteBaseName{currPath, targetSpecificBaseName};
714+
SerializedModuleBaseName absoluteBaseName{currPath,
715+
targetSpecificBaseName};
709716

710717
if (!firstAbsoluteBaseName.has_value())
711718
firstAbsoluteBaseName.emplace(absoluteBaseName);
712719

713720
auto result = findModuleFilesInDirectory(
714721
moduleID, absoluteBaseName, moduleInterfacePath,
715722
moduleInterfaceSourcePath, moduleBuffer, moduleDocBuffer,
716-
moduleSourceInfoBuffer, skipBuildingInterface,
717-
IsFramework, isTestableDependencyLookup);
718-
if (!result) {
723+
moduleSourceInfoBuffer, skipBuildingInterface, IsFramework,
724+
isTestableDependencyLookup);
725+
if (!result)
719726
return SearchResult::Found;
720-
} else if (result == std::errc::not_supported) {
727+
if (result == std::errc::not_supported)
721728
return SearchResult::Error;
722-
} else if (result != std::errc::no_such_file_or_directory) {
729+
if (result != std::errc::no_such_file_or_directory)
723730
return SearchResult::NotFound;
724-
}
725731
}
726732

727733
// We can only get here if all targetFileNamePairs failed with
728734
// 'std::errc::no_such_file_or_directory'.
729-
if (firstAbsoluteBaseName
730-
&& maybeDiagnoseTargetMismatch(moduleID.Loc, moduleName,
731-
*firstAbsoluteBaseName)) {
735+
if (firstAbsoluteBaseName &&
736+
maybeDiagnoseTargetMismatch(moduleID.Loc, moduleName,
737+
*firstAbsoluteBaseName))
732738
return SearchResult::Error;
733-
} else {
734-
return SearchResult::NotFound;
735-
}
739+
740+
return SearchResult::NotFound;
736741
};
737742

738743
SmallVector<std::string, 4> InterestingFilenames = {
@@ -788,13 +793,11 @@ bool SerializedModuleLoaderBase::findModule(
788793
moduleID, absoluteBaseName, moduleInterfacePath,
789794
moduleInterfaceSourcePath, moduleBuffer, moduleDocBuffer,
790795
moduleSourceInfoBuffer, skipBuildingInterface, isFramework);
791-
if (!result) {
796+
if (!result)
792797
return true;
793-
} else if (result == std::errc::not_supported) {
798+
if (result == std::errc::not_supported)
794799
return false;
795-
} else {
796-
continue;
797-
}
800+
continue;
798801
}
799802
case ModuleSearchPathKind::Framework:
800803
case ModuleSearchPathKind::DarwinImplicitFramework: {

test/ScanDependencies/package_interface.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// RUN: %target-swift-frontend -emit-module %t/Bar.swift -I %t \
55
// RUN: -module-name Bar -package-name barpkg \
66
// RUN: -enable-library-evolution -swift-version 5 \
7+
// RUN: -o %t/Bar.swiftmodule \
78
// RUN: -emit-module-interface-path %t/Bar.swiftinterface \
89
// RUN: -emit-private-module-interface-path %t/Bar.private.swiftinterface \
910
// RUN: -emit-package-module-interface-path %t/Bar.package.swiftinterface
@@ -21,10 +22,16 @@
2122
// RUN: %t/Client.swift -module-name Client -swift-version 5
2223
// RUN: %FileCheck %s --input-file=%t/deps3.json --check-prefix CHECK --check-prefix CHECK-PRIVATE
2324

25+
/// If -experimental-package-interface-load is not used but in the same package, it should find the binary module
26+
// RUN: %target-swift-frontend -scan-dependencies -I %t \
27+
// RUN: %t/Client.swift -module-name Client -package-name barpkg -swift-version 5 | \
28+
// RUN: %FileCheck %s --check-prefix CHECK-BINARY
29+
2430
// CHECK: "swift": "Bar"
2531
// CHECK: "modulePath": "{{.*}}{{/|\\}}Bar-{{.*}}.swiftmodule"
2632
// CHECK-PACKAGE: "moduleInterfacePath": "{{.*}}{{/|\\}}Bar.package.swiftinterface"
2733
// CHECK-PRIVATE: "moduleInterfacePath": "{{.*}}{{/|\\}}Bar.private.swiftinterface"
34+
// CHECK-BINARY: "swiftPrebuiltExternal": "Bar"
2835

2936
//--- Bar.swift
3037
public enum PubEnum {

0 commit comments

Comments
 (0)