Skip to content

Commit 87f8650

Browse files
authored
Merge pull request #63974 from xymus/access-level-import-swiftinterface
[ModuleInterface] Hide non-public imports from a resilient module
2 parents f7423b9 + 94aeb8c commit 87f8650

File tree

4 files changed

+158
-2
lines changed

4 files changed

+158
-2
lines changed

include/swift/AST/Module.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,8 @@ class ModuleDecl
757757
Exported = 1 << 0,
758758
/// Include "regular" imports with no special annotation.
759759
Default = 1 << 1,
760-
/// Include imports declared with `@_implementationOnly`.
760+
/// Include imports declared with `@_implementationOnly` or with an
761+
/// access-level of `package` or less.
761762
ImplementationOnly = 1 << 2,
762763
/// Include imports of SPIs declared with `@_spi`.
763764
SPIAccessControl = 1 << 3,

lib/AST/Module.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1887,11 +1887,14 @@ SourceFile::getImportedModules(SmallVectorImpl<ImportedModule> &modules,
18871887
if (!Imports)
18881888
return;
18891889

1890+
bool moduleIsResilient = getParentModule()->getResilienceStrategy() ==
1891+
ResilienceStrategy::Resilient;
18901892
for (auto desc : *Imports) {
18911893
ModuleDecl::ImportFilter requiredFilter;
18921894
if (desc.options.contains(ImportFlags::Exported))
18931895
requiredFilter |= ModuleDecl::ImportFilterKind::Exported;
1894-
else if (desc.options.contains(ImportFlags::ImplementationOnly))
1896+
else if (desc.options.contains(ImportFlags::ImplementationOnly) ||
1897+
(desc.accessLevel <= AccessLevel::Package && moduleIsResilient))
18951898
requiredFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
18961899
else if (desc.options.contains(ImportFlags::SPIOnly))
18971900
requiredFilter |= ModuleDecl::ImportFilterKind::SPIOnly;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/// Check that only public imports are printed in modules interfaces,
2+
/// package imports and below are not.
3+
4+
// RUN: %empty-directory(%t)
5+
// RUN: split-file %s %t
6+
7+
/// Build the libraries.
8+
// RUN: %target-swift-frontend -emit-module %t/PublicLib.swift -o %t \
9+
// RUN: -swift-version 5 -enable-library-evolution
10+
// RUN: %target-swift-frontend -emit-module %t/PackageLib.swift -o %t \
11+
// RUN: -swift-version 5 -enable-library-evolution
12+
// RUN: %target-swift-frontend -emit-module %t/InternalLib.swift -o %t \
13+
// RUN: -swift-version 5 -enable-library-evolution
14+
// RUN: %target-swift-frontend -emit-module %t/FileprivateLib.swift -o %t \
15+
// RUN: -swift-version 5 -enable-library-evolution
16+
// RUN: %target-swift-frontend -emit-module %t/PrivateLib.swift -o %t \
17+
// RUN: -swift-version 5 -enable-library-evolution
18+
19+
/// Build client and generate swiftinterfaces.
20+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \
21+
// RUN: -package-name TestPackage \
22+
// RUN: -enable-library-evolution \
23+
// RUN: -emit-module-interface-path %t/Client.swiftinterface \
24+
// RUN: -emit-private-module-interface-path %t/Client.private.swiftinterface \
25+
// RUN: -enable-experimental-feature AccessLevelOnImport
26+
27+
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t
28+
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.private.swiftinterface) -I %t \
29+
// RUN: -module-name Client
30+
31+
// RUN: %FileCheck -check-prefix=CHECK-PUBLIC %s < %t/Client.swiftinterface
32+
// RUN: %FileCheck -check-prefix=CHECK-PRIVATE %s < %t/Client.private.swiftinterface
33+
34+
/// Build a client composed of many files.
35+
// RUN: %target-swift-frontend -typecheck %t/MultiFiles?.swift -I %t \
36+
// RUN: -package-name TestPackage \
37+
// RUN: -enable-library-evolution \
38+
// RUN: -emit-module-interface-path %t/MultiFiles.swiftinterface \
39+
// RUN: -emit-private-module-interface-path %t/MultiFiles.private.swiftinterface \
40+
// RUN: -enable-experimental-feature AccessLevelOnImport
41+
42+
// RUN: %target-swift-typecheck-module-from-interface(%t/MultiFiles.swiftinterface) -I %t
43+
// RUN: %target-swift-typecheck-module-from-interface(%t/MultiFiles.private.swiftinterface) -I %t \
44+
// RUN: -module-name MultiFiles
45+
46+
// RUN: %FileCheck -check-prefix=CHECK-PUBLIC %s < %t/MultiFiles.swiftinterface
47+
// RUN: %FileCheck -check-prefix=CHECK-PRIVATE %s < %t/MultiFiles.private.swiftinterface
48+
49+
//--- PublicLib.swift
50+
//--- PackageLib.swift
51+
//--- InternalLib.swift
52+
//--- FileprivateLib.swift
53+
//--- PrivateLib.swift
54+
55+
//--- Client.swift
56+
package import PackageLib
57+
// CHECK-PUBLIC-NOT: PackageLib
58+
// CHECK-PRIVATE-NOT: PackageLib
59+
60+
internal import InternalLib
61+
// CHECK-PUBLIC-NOT: InternalLib
62+
// CHECK-PRIVATE-NOT: InternalLib
63+
64+
fileprivate import FileprivateLib
65+
// CHECK-PUBLIC-NOT: FileprivateLib
66+
// CHECK-PRIVATE-NOT: FileprivateLib
67+
68+
private import PrivateLib
69+
// CHECK-PUBLIC-NOT: PrivateLib
70+
// CHECK-PRIVATE-NOT: PrivateLib
71+
72+
//--- MultiFilesA.swift
73+
public import PublicLib
74+
private import InternalLib
75+
76+
//--- MultiFilesB.swift
77+
internal import PublicLib
78+
internal import InternalLib
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/// Check that non-public dependencies are hidden from clients.
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file %s %t
5+
6+
/// Prepare a module to hide or show depending on the import access-level.
7+
// RUN: %target-swift-frontend -emit-module %t/HiddenDep.swift -o %t \
8+
// RUN: -swift-version 5 -enable-library-evolution
9+
10+
//--- HiddenDep.swift
11+
12+
//--- PublicDep.swift
13+
public import HiddenDep
14+
15+
//--- PackageDep.swift
16+
package import HiddenDep
17+
18+
//--- InternalDep.swift
19+
internal import HiddenDep
20+
21+
//--- FileprivateDep.swift
22+
fileprivate import HiddenDep
23+
24+
//--- PrivateDep.swift
25+
private import HiddenDep
26+
27+
/// With resilience, non-public dependencies should be hidden.
28+
// RUN: %target-swift-frontend -emit-module %t/PublicDep.swift -o %t -I %t \
29+
// RUN: -enable-library-evolution \
30+
// RUN: -enable-experimental-feature AccessLevelOnImport
31+
// RUN: %target-swift-frontend -emit-module %t/PackageDep.swift -o %t -I %t \
32+
// RUN: -enable-library-evolution \
33+
// RUN: -enable-experimental-feature AccessLevelOnImport
34+
// RUN: %target-swift-frontend -emit-module %t/InternalDep.swift -o %t -I %t \
35+
// RUN: -enable-library-evolution \
36+
// RUN: -enable-experimental-feature AccessLevelOnImport
37+
// RUN: %target-swift-frontend -emit-module %t/FileprivateDep.swift -o %t -I %t \
38+
// RUN: -enable-library-evolution \
39+
// RUN: -enable-experimental-feature AccessLevelOnImport
40+
// RUN: %target-swift-frontend -emit-module %t/PrivateDep.swift -o %t -I %t \
41+
// RUN: -enable-library-evolution \
42+
// RUN: -enable-experimental-feature AccessLevelOnImport
43+
44+
// RUN: %target-swift-frontend -typecheck %t/ClientOfPublic.swift -I %t \
45+
// RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=VISIBLE-PACKAGE-DEP %s
46+
// VISIBLE-PACKAGE-DEP: source: '{{.*}}HiddenDep.swiftmodule'
47+
//--- ClientOfPublic.swift
48+
import PublicDep
49+
50+
// RUN: %target-swift-frontend -typecheck %t/ClientOfNonPublic.swift -I %t \
51+
// RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=HIDDEN-PACKAGE-DEP %s
52+
// HIDDEN-PACKAGE-DEP-NOT: HiddenDep
53+
//--- ClientOfNonPublic.swift
54+
import PackageDep
55+
import InternalDep
56+
import FileprivateDep
57+
import PrivateDep
58+
59+
/// Without resilience, all access-level dependencies are visible to clients.
60+
// RUN: %target-swift-frontend -emit-module %t/PublicDep.swift -o %t -I %t \
61+
// RUN: -enable-experimental-feature AccessLevelOnImport
62+
// RUN: %target-swift-frontend -emit-module %t/PackageDep.swift -o %t -I %t \
63+
// RUN: -enable-experimental-feature AccessLevelOnImport
64+
// RUN: %target-swift-frontend -emit-module %t/InternalDep.swift -o %t -I %t \
65+
// RUN: -enable-experimental-feature AccessLevelOnImport
66+
// RUN: %target-swift-frontend -emit-module %t/FileprivateDep.swift -o %t -I %t \
67+
// RUN: -enable-experimental-feature AccessLevelOnImport
68+
// RUN: %target-swift-frontend -emit-module %t/PrivateDep.swift -o %t -I %t \
69+
// RUN: -enable-experimental-feature AccessLevelOnImport
70+
71+
// RUN: %target-swift-frontend -typecheck %t/ClientOfPublic.swift -I %t \
72+
// RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=VISIBLE-PACKAGE-DEP %s
73+
// RUN: %target-swift-frontend -typecheck %t/ClientOfNonPublic.swift -I %t \
74+
// RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=VISIBLE-PACKAGE-DEP %s

0 commit comments

Comments
 (0)