Skip to content

Commit 59940b7

Browse files
authored
[ModuleInterface] Filter using access control and @usableFromInline (#18521)
These are the parts of a (resilient) module that affect the public interface and ABI; everything else is uninteresting. Or at least ought to be.
1 parent 88d2feb commit 59940b7

File tree

3 files changed

+119
-3
lines changed

3 files changed

+119
-3
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,24 @@ PrintOptions PrintOptions::printTextualInterfaceFile() {
7171
result.PrintIfConfig = false;
7272
result.FullyQualifiedTypes = true;
7373
result.SkipImports = true;
74-
result.AccessFilter = AccessLevel::Public;
74+
75+
class UsableFromInlineOnly : public ShouldPrintChecker {
76+
bool shouldPrint(const Decl *D, PrintOptions &options) override {
77+
if (auto *VD = dyn_cast<ValueDecl>(D)) {
78+
AccessScope accessScope =
79+
VD->getFormalAccessScope(/*useDC*/nullptr,
80+
/*treatUsableFromInlineAsPublic*/true);
81+
if (!accessScope.isPublic())
82+
return false;
83+
}
84+
return ShouldPrintChecker::shouldPrint(D, options);
85+
}
86+
};
87+
result.CurrentPrintabilityChecker = std::make_shared<UsableFromInlineOnly>();
88+
89+
// FIXME: We don't really need 'public' on everything; we could just change
90+
// the default to 'public' and mark the 'internal' things.
91+
result.PrintAccess = true;
7592

7693
// FIXME: We'll need the actual default parameter expression.
7794
result.PrintDefaultParameterPlaceholder = false;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
2+
// RUN: %FileCheck %s < %t.swiftinterface
3+
// RUN: %FileCheck -check-prefix NEGATIVE %s < %t.swiftinterface
4+
5+
// NEGATIVE-NOT: BAD
6+
7+
// CHECK: public func publicFn(){{$}}
8+
public func publicFn() {}
9+
internal func internalFn_BAD() {}
10+
private func privateFn_BAD() {}
11+
12+
// CHECK: @usableFromInline
13+
// CHECK-NEXT: internal func ufiFn(){{$}}
14+
@usableFromInline internal func ufiFn() {}
15+
16+
17+
// CHECK: public struct PublicStruct {{[{]$}}
18+
public struct PublicStruct {
19+
// CHECK: public func publicMethod(){{$}}
20+
public func publicMethod() {}
21+
internal func internalMethod_BAD() {}
22+
23+
// CHECK: @usableFromInline
24+
// CHECK-NEXT: internal func ufiMethod(){{$}}
25+
@usableFromInline internal func ufiMethod() {}
26+
} // CHECK: {{^[}]$}}
27+
28+
internal struct InternalStruct_BAD {
29+
public func publicMethod_BAD() {}
30+
internal func internalMethod_BAD() {}
31+
@usableFromInline internal func ufiMethod_BAD() {}
32+
}
33+
34+
// CHECK: @usableFromInline
35+
// CHECK-NEXT: internal struct UFIStruct {{[{]$}}
36+
@usableFromInline
37+
internal struct UFIStruct {
38+
// FIXME: Arguably this should be downgraded to "@usableFromInline internal".
39+
// CHECK: public func publicMethod(){{$}}
40+
public func publicMethod() {}
41+
internal func internalMethod_BAD() {}
42+
43+
// CHECK: @usableFromInline
44+
// CHECK-NEXT: internal func ufiMethod(){{$}}
45+
@usableFromInline internal func ufiMethod() {}
46+
} // CHECK: {{^[}]$}}
47+
48+
// CHECK: public protocol PublicProto {{[{]$}}
49+
public protocol PublicProto {
50+
} // CHECK: {{^[}]$}}
51+
52+
// CHECK: extension PublicProto {{[{]$}}
53+
extension PublicProto {
54+
// CHECK: public func publicMethod(){{$}}
55+
public func publicMethod() {}
56+
internal func internalMethod_BAD() {}
57+
58+
// CHECK: @usableFromInline
59+
// CHECK-NEXT: internal func ufiMethod(){{$}}
60+
@usableFromInline internal func ufiMethod() {}
61+
} // CHECK: {{^[}]$}}
62+
63+
// FIXME: We shouldn't print access on extensions in textual interface files.
64+
// CHECK: {{^}}public extension PublicProto {{[{]$}}
65+
public extension PublicProto {
66+
// CHECK: public func publicExtPublicMethod(){{$}}
67+
func publicExtPublicMethod() {}
68+
internal func publicExtInternalMethod_BAD() {}
69+
70+
// CHECK: @usableFromInline
71+
// CHECK-NEXT: internal func publicExtUFIMethod(){{$}}
72+
@usableFromInline internal func publicExtUFIMethod() {}
73+
}
74+
75+
internal protocol InternalProto_BAD {
76+
}
77+
78+
extension InternalProto_BAD {
79+
public func publicMethod_BAD() {}
80+
internal func internalMethod_BAD() {}
81+
@usableFromInline internal func ufiMethod_BAD() {}
82+
}
83+
84+
// CHECK: @usableFromInline
85+
// CHECK-NEXT: internal protocol UFIProto {{[{]$}}
86+
@usableFromInline
87+
internal protocol UFIProto {
88+
} // CHECK: {{^[}]$}}
89+
90+
// CHECK: extension UFIProto {{[{]$}}
91+
extension UFIProto {
92+
// CHECK: public func publicMethod(){{$}}
93+
public func publicMethod() {}
94+
internal func internalMethod_BAD() {}
95+
96+
// CHECK: @usableFromInline
97+
// CHECK-NEXT: internal func ufiMethod(){{$}}
98+
@usableFromInline internal func ufiMethod() {}
99+
} // CHECK: {{^[}]$}}

test/ModuleInterface/print-from-partial-modules.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %target-swift-frontend -emit-module -o %t/other~partial.swiftmodule %s -primary-file %S/Inputs/other.swift -module-name main
44
// RUN: %target-swift-frontend -merge-modules -emit-module -o /dev/null -emit-interface-path - %t/main~partial.swiftmodule -module-name main %t/other~partial.swiftmodule | %FileCheck %s
55

6-
// CHECK: {{^}}func verySimpleFunction(){{$}}
6+
// CHECK: {{^}}public func verySimpleFunction(){{$}}
77
public func verySimpleFunction() {}
88

9-
// CHECK: {{^}}func otherFileFunction(){{$}}
9+
// CHECK: {{^}}public func otherFileFunction(){{$}}

0 commit comments

Comments
 (0)