Skip to content

Commit e9f847d

Browse files
authored
Merge pull request #65336 from apple/es-private
Print package-name in .private.swiftinterface only for better abstraction
2 parents 6b2d4bd + e6bc110 commit e9f847d

12 files changed

+163
-49
lines changed

include/swift/Frontend/ModuleInterfaceSupport.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define SWIFT_COMPILER_VERSION_KEY "swift-compiler-version"
2222
#define SWIFT_MODULE_FLAGS_KEY "swift-module-flags"
2323
#define SWIFT_MODULE_FLAGS_IGNORABLE_KEY "swift-module-flags-ignorable"
24+
#define SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY "swift-module-flags-ignorable-private"
2425

2526
namespace swift {
2627

@@ -50,6 +51,10 @@ struct ModuleInterfaceOptions {
5051
/// ignored by the earlier version of the compiler.
5152
std::string IgnorableFlags;
5253

54+
/// Ignorable flags that should only be printed in .private.swiftinterface file;
55+
/// e.g. -package-name PACKAGE_ID
56+
std::string IgnorablePrivateFlags;
57+
5358
/// Print for a private swiftinterface file, SPI decls and attributes.
5459
bool PrintPrivateInterfaceContent = false;
5560

include/swift/Option/Options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ namespace options {
4242
SwiftAPIDigesterOption = (1 << 17),
4343
NewDriverOnlyOption = (1 << 18),
4444
ModuleInterfaceOptionIgnorable = (1 << 19),
45+
ModuleInterfaceOptionIgnorablePrivate = (1 << 20),
4546
};
4647

4748
enum ID {

include/swift/Option/Options.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ def ModuleInterfaceOption : OptionFlag;
5656
// The option can be safely ignored by the older compiler.
5757
def ModuleInterfaceOptionIgnorable : OptionFlag;
5858

59+
// The option should be written into a .private.swiftinterface module interface file,
60+
// and read/parsed from there when reconstituting a .swiftmodule from it.
61+
// The option can be safely ignored by the older compiler.
62+
def ModuleInterfaceOptionIgnorablePrivate : OptionFlag;
63+
5964
// The option causes the output of a supplementary output, or is the path option
6065
// for a supplementary output. E.g., `-emit-module` and `-emit-module-path`.
6166
def SupplementaryOutput : OptionFlag;
@@ -530,7 +535,7 @@ def module_abi_name : Separate<["-"], "module-abi-name">,
530535
Flags<[FrontendOption, ModuleInterfaceOption]>,
531536
HelpText<"ABI name to use for the contents of this module">;
532537
def package_name : Separate<["-"], "package-name">,
533-
Flags<[FrontendOption, ModuleInterfaceOptionIgnorable]>,
538+
Flags<[FrontendOption, ModuleInterfaceOptionIgnorablePrivate]>,
534539
HelpText<"Name of the package the module belongs to">;
535540
def export_as : Separate<["-"], "export-as">,
536541
Flags<[FrontendOption, ModuleInterfaceOptionIgnorable]>,

lib/AST/Decl.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3972,11 +3972,17 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
39723972
case AccessLevel::Package: {
39733973
auto pkg = resultDC->getPackageContext(/*lookupIfNotCurrent*/ true);
39743974
if (!pkg) {
3975-
// No package context was found; show diagnostics
3976-
auto &d = VD->getASTContext().Diags;
3977-
d.diagnose(VD->getLoc(), diag::access_control_requires_package_name);
3978-
// Instead of reporting and failing early, return the scope of
3979-
// resultDC to allow continuation (should still non-zero exit later)
3975+
auto srcFile = resultDC->getParentSourceFile();
3976+
// Check if the file containing package decls is an interface file; if a public
3977+
// interface contains package decls, they must be inlinable and do not need a
3978+
// package-name, so don't show diagnostics in that case.
3979+
if (srcFile && srcFile->Kind != SourceFileKind::Interface) {
3980+
// No package context was found; show diagnostics
3981+
auto &d = VD->getASTContext().Diags;
3982+
d.diagnose(VD->getLoc(), diag::access_control_requires_package_name);
3983+
}
3984+
// Instead of reporting and failing early, return the scope of resultDC to
3985+
// allow continuation (should still non-zero exit later if in script mode)
39803986
return AccessScope(resultDC);
39813987
} else {
39823988
return AccessScope(pkg);
@@ -4168,9 +4174,16 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
41684174
return useSF && useSF->hasTestableOrPrivateImport(access, sourceModule);
41694175
}
41704176
case AccessLevel::Package: {
4171-
auto srcPkg = sourceDC->getPackageContext(/*lookupIfNotCurrent*/ true);
4172-
auto usePkg = useDC->getPackageContext(/*lookupIfNotCurrent*/ true);
4173-
return usePkg->isSamePackageAs(srcPkg);
4177+
auto srcFile = sourceDC->getParentSourceFile();
4178+
if (srcFile && srcFile->Kind != SourceFileKind::Interface) {
4179+
auto srcPkg = sourceDC->getPackageContext(/*lookupIfNotCurrent*/ true);
4180+
auto usePkg = useDC->getPackageContext(/*lookupIfNotCurrent*/ true);
4181+
return usePkg->isSamePackageAs(srcPkg);
4182+
} else {
4183+
// If source file is interface, package decls must be inlinable,
4184+
// essentially treated public so return true (see AccessLevel::Public)
4185+
return true;
4186+
}
41744187
}
41754188
case AccessLevel::Public:
41764189
case AccessLevel::Open:

lib/Frontend/CompilerInvocation.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,11 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
426426
return;
427427
ArgStringList RenderedArgs;
428428
ArgStringList RenderedArgsIgnorable;
429+
ArgStringList RenderedArgsIgnorablePrivate;
429430
for (auto A : Args) {
430-
if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) {
431+
if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorablePrivate)) {
432+
A->render(Args, RenderedArgsIgnorablePrivate);
433+
} else if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) {
431434
A->render(Args, RenderedArgsIgnorable);
432435
} else if (A->getOption().hasFlag(options::ModuleInterfaceOption)) {
433436
A->render(Args, RenderedArgs);
@@ -446,6 +449,12 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
446449
if (FOpts.ModuleName == "_Concurrency")
447450
OS << " -disable-availability-checking";
448451
}
452+
{
453+
llvm::raw_string_ostream OS(Opts.IgnorablePrivateFlags);
454+
interleave(RenderedArgsIgnorablePrivate,
455+
[&](const char *Argument) { PrintArg(OS, Argument, StringRef()); },
456+
[&] { OS << " "; });
457+
}
449458
{
450459
llvm::raw_string_ostream OS(Opts.IgnorableFlags);
451460
interleave(RenderedArgsIgnorable,

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,8 +1249,8 @@ ModuleDecl *CompilerInstance::getMainModule() const {
12491249
Invocation.getFrontendOptions().ModuleABIName));
12501250
}
12511251
if (!Invocation.getLangOptions().PackageName.empty()) {
1252-
MainModule->setPackageName(getASTContext().getIdentifier(
1253-
Invocation.getLangOptions().PackageName));
1252+
auto pkgName = Invocation.getLangOptions().PackageName;
1253+
MainModule->setPackageName(getASTContext().getIdentifier(pkgName));
12541254
}
12551255
if (!Invocation.getFrontendOptions().ExportAsName.empty()) {
12561256
MainModule->setExportAsName(getASTContext().getIdentifier(

lib/Frontend/ModuleInterfaceSupport.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ static void printToolVersionAndFlagsComment(raw_ostream &out,
9898
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_KEY ": "
9999
<< Opts.IgnorableFlags << "\n";
100100
}
101+
102+
auto hasPrivateIgnorableFlags = Opts.PrintPrivateInterfaceContent && !Opts.IgnorablePrivateFlags.empty();
103+
if (hasPrivateIgnorableFlags) {
104+
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY ": "
105+
<< Opts.IgnorablePrivateFlags << "\n";
106+
}
101107
}
102108

103109
std::string

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,12 +1171,25 @@ bool swift::extractCompilerFlagsFromInterface(StringRef interfacePath,
11711171
// Cherry-pick supported options from the ignorable list.
11721172
auto IgnFlagRe = llvm::Regex("^// swift-module-flags-ignorable:(.*)$",
11731173
llvm::Regex::Newline);
1174-
// It's OK the interface doesn't have the ignorable list, we just ignore them
1175-
// all.
1176-
if (!IgnFlagRe.match(buffer, &IgnFlagMatches))
1174+
auto hasIgnorableFlags = IgnFlagRe.match(buffer, &IgnFlagMatches);
1175+
1176+
// Check for ignorable-private flags
1177+
SmallVector<StringRef, 1> IgnPrivateFlagMatches;
1178+
auto IgnPrivateFlagRe = llvm::Regex("^// swift-module-flags-ignorable-private:(.*)$",
1179+
llvm::Regex::Newline);
1180+
auto hasIgnorablePrivateFlags = IgnPrivateFlagRe.match(buffer, &IgnPrivateFlagMatches);
1181+
1182+
// It's OK the interface doesn't have the ignorable list (private or not), we just
1183+
// ignore them all.
1184+
if (!hasIgnorableFlags && !hasIgnorablePrivateFlags)
11771185
return false;
1186+
11781187
SmallVector<const char *, 8> IgnSubArgs;
1179-
llvm::cl::TokenizeGNUCommandLine(IgnFlagMatches[1], ArgSaver, IgnSubArgs);
1188+
if (hasIgnorableFlags)
1189+
llvm::cl::TokenizeGNUCommandLine(IgnFlagMatches[1], ArgSaver, IgnSubArgs);
1190+
if (hasIgnorablePrivateFlags)
1191+
llvm::cl::TokenizeGNUCommandLine(IgnPrivateFlagMatches[1], ArgSaver, IgnSubArgs);
1192+
11801193
std::unique_ptr<llvm::opt::OptTable> table = swift::createSwiftOptTable();
11811194
unsigned missingArgIdx = 0;
11821195
unsigned missingArgCount = 0;

test/Sema/accessibility_package_inline_interface.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
// RUN: %target-swift-typecheck-module-from-interface(%t/Utils.swiftinterface) -I%t
1010

1111
// RUN: %FileCheck %s -check-prefix CHECK-UTILS < %t/Utils.swiftinterface
12-
// CHECK-UTILS: -module-name Utils -enable-library-evolution
13-
// CHECK-UTILS: swift-module-flags-ignorable: -package-name myLib
12+
// CHECK-UTILS-NOT: -package-name myLib
13+
// CHECK-UTILS: -module-name Utils
1414
// CHECK-UTILS: @usableFromInline
1515
// CHECK-UTILS: package class PackageKlassProto {
1616
// CHECK-UTILS: @usableFromInline
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-frontend -emit-module %t/Utils.swift \
5+
// RUN: -module-name Utils -swift-version 5 -I %t \
6+
// RUN: -package-name swift-utils.log \
7+
// RUN: -enable-library-evolution \
8+
// RUN: -emit-module-path %t/Utils.swiftmodule \
9+
// RUN: -emit-module-interface-path %t/Utils.swiftinterface \
10+
// RUN: -emit-private-module-interface-path %t/Utils.private.swiftinterface
11+
12+
// RUN: %target-swift-typecheck-module-from-interface(%t/Utils.swiftinterface) -I %t
13+
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/Utils.swiftinterface
14+
// CHECK-PUBLIC-NOT: -package-name swift-utils.log
15+
// CHECK-PUBLIC-NOT: package func packageFunc()
16+
// CHECK-PUBLIC: -module-name Utils
17+
// CHECK-PUBLIC: public func publicFunc()
18+
19+
// RUN: %target-swift-typecheck-module-from-interface(%t/Utils.private.swiftinterface) -module-name Utils -I %t
20+
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/Utils.private.swiftinterface
21+
22+
// CHECK-PRIVATE-NOT: package func packageFunc()
23+
// CHECK-PRIVATE: swift-module-flags-ignorable-private: -package-name swift-utils.log
24+
// CHECK-PRIVATE: public func publicFunc()
25+
26+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -package-name swift-utils.log -I %t -verify
27+
28+
//--- Utils.swift
29+
package func packageFunc() {}
30+
public func publicFunc() {}
31+
32+
//--- Client.swift
33+
import Utils
34+
35+
func clientFunc() {
36+
packageFunc()
37+
publicFunc()
38+
}

test/Serialization/load_package_module.swift

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,57 @@
11
// RUN: %empty-directory(%t)
22
// RUN: split-file %s %t
33

4-
// RUN: %target-swift-frontend -module-name LibFromInterface -emit-module -emit-module-interface-path %t/LibFromInterface.swiftinterface -parse-as-library %t/Lib.swift -enable-library-evolution -package-name mypkg -swift-version 5
5-
// RUN: test -f %t/LibFromInterface.swiftinterface
6-
// RUN: %FileCheck %s -check-prefix CHECK-LIB < %t/LibFromInterface.swiftinterface
7-
// CHECK-LIB: -package-name mypkg
8-
// CHECK-LIB-NOT: func log(level: Int)
4+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
5+
// RUN: -module-name LibBinary -swift-version 5 -I %t \
6+
// RUN: -package-name libPkg \
7+
// RUN: -emit-module-path %t/LibBinary.swiftmodule
98

10-
// RUN: not %target-swift-frontend -module-name ClientInSamePkg %t/ClientLoadInterfaceModule.swift -emit-module -emit-module-path %t/ClientInSamePkg.swiftmodule -package-name mypkg -I %t 2> %t/resultA.output
11-
// RUN: %FileCheck %s -check-prefix CHECK-A < %t/resultA.output
12-
// CHECK-A: error: module 'LibFromInterface' is in package 'mypkg' but was built from interface; modules of the same package can only be loaded if built from source: {{.*}}LibFromInterface.swiftinterface
9+
// RUN: %target-swift-frontend -typecheck %t/ClientLoadBinary.swift -package-name libPkg -I %t -verify
1310

14-
// RUN: not %target-swift-frontend -module-name ClientInDiffPkg %t/ClientLoadInterfaceModule.swift -emit-module -emit-module-path %t/ClientInDiffPkg.swiftmodule -package-name otherPkg -I %t 2> %t/resultB.output
15-
// RUN: %FileCheck %s -check-prefix CHECK-B < %t/resultB.output
16-
// CHECK-B: error: cannot find 'log' in scope
11+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
12+
// RUN: -module-name LibInterface -swift-version 5 -I %t \
13+
// RUN: -package-name libPkg \
14+
// RUN: -enable-library-evolution \
15+
// RUN: -emit-module-path %t/LibBinary.swiftmodule \
16+
// RUN: -emit-module-interface-path %t/LibInterface.swiftinterface \
17+
// RUN: -emit-private-module-interface-path %t/LibInterface.private.swiftinterface
1718

18-
// RUN: %target-swift-frontend -module-name LibFromSource -emit-module -emit-module-path %t/LibFromSource.swiftmodule -parse-as-library %t/Lib.swift -package-name mypkg
19-
// RUN: test -f %t/LibFromSource.swiftmodule
19+
// RUN: %target-swift-typecheck-module-from-interface(%t/LibInterface.swiftinterface) -I %t
20+
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/LibInterface.swiftinterface
21+
// CHECK-PUBLIC: -module-name LibInterface
22+
// CHECK-PUBLIC-NOT: -package-name
23+
24+
// RUN: %target-swift-typecheck-module-from-interface(%t/LibInterface.private.swiftinterface) -module-name LibInterface -I %t
25+
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/LibInterface.private.swiftinterface
26+
// CHECK-PRIVATE: swift-module-flags-ignorable-private: -package-name libPkg
27+
28+
// RUN: not %target-swift-frontend -typecheck %t/ClientLoadInterface.swift -package-name otherPkg -I %t 2> %t/resultX.output
29+
// RUN: %FileCheck %s -check-prefix CHECK-X < %t/resultX.output
30+
// CHECK-X: error: cannot find 'packageLog' in scope
31+
32+
// RUN: not %target-swift-frontend -typecheck %t/ClientLoadInterface.swift -package-name libPkg -I %t 2> %t/resultY.output
33+
// RUN: %FileCheck %s -check-prefix CHECK-Y < %t/resultY.output
34+
// CHECK-Y: error: module 'LibInterface' is in package 'libPkg' but was built from interface; modules of the same package can only be loaded if built from source: {{.*}}LibInterface.private.swiftinterface
2035

21-
// RUN: %target-swift-frontend -module-name ClientInSamePkgSrc %t/ClientLoadSourceModule.swift -emit-module -emit-module-path %t/ClientInSamePkgSrc.swiftmodule -package-name mypkg -I %t
22-
// RUN: test -f %t/ClientInSamePkgSrc.swiftmodule
2336

2437
//--- Lib.swift
25-
package func log(level: Int) {}
38+
public func publicLog(_ level: Int) {}
39+
package func packageLog(_ level: Int) {}
40+
func internalLog(_ level: Int) {}
2641

27-
//--- ClientLoadInterfaceModule.swift
28-
import LibFromInterface
2942

30-
func someFun() {
31-
log(level: 1)
43+
//--- ClientLoadInterface.swift
44+
import LibInterface
45+
46+
func someFunc() {
47+
publicLog(1)
48+
packageLog(2)
3249
}
3350

34-
//--- ClientLoadSourceModule.swift
35-
import LibFromSource
51+
//--- ClientLoadBinary.swift
52+
import LibBinary
3653

37-
func someFun() {
38-
log(level: 1)
54+
func someFunc() {
55+
publicLog(1)
56+
packageLog(2)
3957
}
40-
Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %{python} %utils/split_file.py -o %t %s
2+
// RUN: split-file %s %t
33

44
// RUN: %target-swift-frontend -module-name Logging -package-name MyLoggingPkg %t/File.swift -emit-module -emit-module-path %t/Logging.swiftmodule
55
// RUN: test -f %t/Logging.swiftmodule
66
// RUN: llvm-bcanalyzer -dump %t/Logging.swiftmodule | %FileCheck %s -check-prefix CHECK-BLOB
77
// CHECK-BLOB: <MODULE_PACKAGE_NAME abbrevid=5/> blob data = 'MyLoggingPkg'
88

9-
// RUN: %target-swift-frontend -module-name Logging -package-name MyLoggingPkg %t/File.swift -emit-module -emit-module-interface-path %t/Logging.swiftinterface -swift-version 5 -enable-library-evolution -I %t
10-
// RUN: test -f %t/Logging.swiftinterface
11-
// RUN: %FileCheck %s -input-file %t/Logging.swiftinterface -check-prefix CHECK-FLAG
12-
// CHECK-FLAG: -package-name MyLoggingPkg
9+
// RUN: %target-swift-frontend -module-name Logging -package-name MyLoggingPkg %t/File.swift -emit-module -emit-module-interface-path %t/Logging.swiftinterface -emit-private-module-interface-path %t/Logging.private.swiftinterface -swift-version 5 -enable-library-evolution -I %t
1310

14-
// BEGIN File.swift
11+
// RUN: %target-swift-typecheck-module-from-interface(%t/Logging.swiftinterface) -I %t
12+
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/Logging.swiftinterface
13+
// CHECK-PUBLIC: -module-name Logging
14+
// CHECK-PUBLIC-NOT: -package-name
15+
16+
// RUN: %target-swift-typecheck-module-from-interface(%t/Logging.private.swiftinterface) -module-name Logging -I %t
17+
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/Logging.private.swiftinterface
18+
// CHECK-PRIVATE: -module-name Logging
19+
// CHECK-PRIVATE: swift-module-flags-ignorable-private: -package-name MyLoggingPkg
20+
21+
//--- File.swift
1522
public func log(level: Int) {}

0 commit comments

Comments
 (0)