Skip to content

Correct discrepancies in the package interface file lookup. #75160

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 2 commits into from
Jul 12, 2024
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
15 changes: 8 additions & 7 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,9 +618,6 @@ std::string SerializedModuleBaseName::getName(file_types::ID fileTy) const {
std::optional<std::string>
SerializedModuleBaseName::getPackageInterfacePathIfInSamePackage(
llvm::vfs::FileSystem &fs, ASTContext &ctx) const {
if (!ctx.LangOpts.EnablePackageInterfaceLoad)
return std::nullopt;

std::string packagePath{
getName(file_types::TY_PackageSwiftModuleInterfaceFile)};

Expand Down Expand Up @@ -667,11 +664,15 @@ SerializedModuleBaseName::findInterfacePath(llvm::vfs::FileSystem &fs,
if (!fs.exists(interfacePath))
return std::nullopt;

// If there is a package name, try look for the package interface.
if (!ctx.LangOpts.PackageName.empty()) {
if (auto maybePackageInterface =
// If both -package-name and -experimental-package-interface-load
// are passed to the client, try to look for the package interface
// to load; if either flag is missing, fall back to loading private
// or public interface.
if (!ctx.LangOpts.PackageName.empty() &&
ctx.LangOpts.EnablePackageInterfaceLoad) {
if (auto found =
getPackageInterfacePathIfInSamePackage(fs, ctx))
return *maybePackageInterface;
return *found;

// If package interface is not found, check if we can load the
// public/private interface file by checking:
Expand Down
5 changes: 3 additions & 2 deletions test/ModuleInterface/load_package_interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@

// CHECK-LOAD-PKG-ENABLED: loaded module 'Bar'; source: '{{.*}}Bar.package.swiftinterface', loaded: '{{.*}}Bar-{{.*}}.swiftmodule'

/// Client should not load a package interface module without the flag or the env var
/// Client should not load a package interface without the flag or the env var above;
/// in such case, private swiftinterface is loaded but an error should be thrown in typecheck.
// RUN: not %target-swift-frontend -typecheck %t/Client.swift -I %t \
// RUN: -package-name barpkg \
// RUN: -Rmodule-loading 2> %t/load-pkg-off.output
// RUN: %FileCheck -check-prefix=CHECK-LOAD-PKG-OFF %s < %t/load-pkg-off.output
// CHECK-LOAD-PKG-OFF: no such module 'Bar'
// CHECK-LOAD-PKG-OFF: error: module 'Bar' is in package 'barpkg' but was built from a non-package interface; modules of the same package can only be loaded if built from source or package interface:{{.*}}Bar.private.swiftinterface

/// Client loads a private interface since the package-name is different from the loaded module's.
// RUN: not %target-swift-frontend -typecheck %t/Client.swift -I %t \
Expand Down
23 changes: 14 additions & 9 deletions test/ScanDependencies/package_interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,34 @@
// RUN: -emit-private-module-interface-path %t/Bar.private.swiftinterface \
// RUN: -emit-package-module-interface-path %t/Bar.package.swiftinterface

// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps.json -I %t -experimental-package-interface-load \
// RUN: %t/Client.swift -module-name Client -package-name barpkg -swift-version 5
// RUN: %target-swift-frontend -scan-dependencies \
// RUN: -module-load-mode prefer-interface -o %t/deps.json -I %t \
// RUN: -experimental-package-interface-load -swift-version 5 \
// RUN: %t/Client.swift -module-name Client -package-name barpkg
// RUN: %FileCheck %s --input-file=%t/deps.json --check-prefix CHECK --check-prefix CHECK-PACKAGE

/// When package name doesn't match or not used, it should find private interface.
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps2.json -I %t -experimental-package-interface-load \
// RUN: %t/Client.swift -module-name Client -package-name foopkg -swift-version 5
// RUN: %FileCheck %s --input-file=%t/deps2.json --check-prefix CHECK --check-prefix CHECK-PRIVATE

// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps3.json -I %t -experimental-package-interface-load \
// RUN: %t/Client.swift -module-name Client -swift-version 5
// RUN: %target-swift-frontend -scan-dependencies \
// RUN: -module-load-mode prefer-interface -o %t/deps3.json -I %t \
// RUN: -experimental-package-interface-load -swift-version 5 \
// RUN: %t/Client.swift -module-name Client
// RUN: %FileCheck %s --input-file=%t/deps3.json --check-prefix CHECK --check-prefix CHECK-PRIVATE

/// If -experimental-package-interface-load is not used but in the same package, it should find the binary module
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -I %t \
// RUN: %t/Client.swift -module-name Client -package-name barpkg -swift-version 5 | \
// RUN: %FileCheck %s --check-prefix CHECK-BINARY
/// If -experimental-package-interface-load is not used but in the same package, it should find private interface.
// RUN: %target-swift-frontend -scan-dependencies \
// RUN: -module-load-mode prefer-interface -o %t/deps4.json -I %t \
// RUN: -swift-version 5 \
// RUN: %t/Client.swift -module-name Client -package-name barpkg | \
// RUN: %FileCheck %s --input-file=%t/deps4.json --check-prefix CHECK-PRIVATE

// CHECK: "swift": "Bar"
// CHECK: "modulePath": "{{.*}}{{/|\\}}Bar-{{.*}}.swiftmodule"
// CHECK-PACKAGE: "moduleInterfacePath": "{{.*}}{{/|\\}}Bar.package.swiftinterface"
// CHECK-PRIVATE: "moduleInterfacePath": "{{.*}}{{/|\\}}Bar.private.swiftinterface"
// CHECK-BINARY: "swiftPrebuiltExternal": "Bar"

//--- Bar.swift
public enum PubEnum {
Expand Down
2 changes: 1 addition & 1 deletion test/Serialization/load_package_module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

// RUN: not %target-swift-frontend -typecheck %t/ClientLoadInterface.swift -package-name libPkg -I %t 2> %t/resultY.output
// RUN: %FileCheck %s -check-prefix CHECK-Y < %t/resultY.output
// CHECK-Y: error: no such module 'LibInterface'
// CHECK-Y: error: module 'LibInterface' is in package 'libPkg' but was built from a non-package interface; modules of the same package can only be loaded if built from source or package interface: {{.*}}LibInterface.private.swiftinterface


//--- Lib.swift
Expand Down