Skip to content

Commit a4128d6

Browse files
authored
Merge pull request #85182 from xymus/non-neic-funcs-and-spi
Sema: Allow more references to restricted decls from embedded code
2 parents 2ba29d3 + 0e7077d commit a4128d6

File tree

5 files changed

+222
-41
lines changed

5 files changed

+222
-41
lines changed

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,8 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
9898
}
9999

100100
// Embedded functions can reference non-public decls as they are visible
101-
// to clients. Still report references to decls imported non-publicly
102-
// to enforce access-level on imports.
103-
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
104-
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient &&
105-
!problematicImport)
101+
// to clients.
102+
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient)
106103
return false;
107104

108105
DowngradeToWarning downgradeToWarning = DowngradeToWarning::No;
@@ -135,6 +132,7 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
135132

136133
Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D);
137134

135+
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
138136
if (problematicImport.has_value() &&
139137
problematicImport->accessLevel < D->getFormalAccess()) {
140138
Context.Diags.diagnose(problematicImport->importLoc,
@@ -298,6 +296,7 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
298296
}
299297
});
300298

299+
auto fragileKind = where.getFragileFunctionKind();
301300
switch (originKind) {
302301
case DisallowedOriginKind::None:
303302
// The decl does not come from a source that needs to be checked for
@@ -329,11 +328,15 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
329328
if (reason && reason == ExportabilityReason::AvailableAttribute &&
330329
ctx.LangOpts.LibraryLevel == LibraryLevel::API)
331330
return false;
332-
break;
331+
LLVM_FALLTHROUGH;
333332

334-
case DisallowedOriginKind::ImplementationOnly:
335333
case DisallowedOriginKind::SPIImported:
336334
case DisallowedOriginKind::SPILocal:
335+
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient)
336+
return false;
337+
break;
338+
339+
case DisallowedOriginKind::ImplementationOnly:
337340
case DisallowedOriginKind::FragileCxxAPI:
338341
break;
339342
}
@@ -345,7 +348,6 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
345348
return false;
346349
}
347350

348-
auto fragileKind = where.getFragileFunctionKind();
349351
if (fragileKind.kind == FragileFunctionKind::None) {
350352
DiagnosticBehavior limit = downgradeToWarning == DowngradeToWarning::Yes
351353
? DiagnosticBehavior::Warning

test/Sema/Inputs/implementation-only-imports/indirects.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ public typealias GenericAliasFromIndirect<T> = (StructFromIndirect, T)
66

77
public func globalFunctionFromIndirect() {}
88
public var globalVariableFromIndirect = 0
9+
10+
@_spi(S) public func spiFunctionFromDirect() {}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/// Test @_implementationOnly internal import exportability diagnostics in embedded mode.
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule \
5+
// RUN: %S/Inputs/implementation-only-imports/indirects.swift \
6+
// RUN: -swift-version 5 -target arm64-apple-none-macho \
7+
// RUN: -enable-experimental-feature Embedded
8+
// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t \
9+
// RUN: %S/Inputs/implementation-only-imports/directs.swift \
10+
// RUN: -swift-version 5 -target arm64-apple-none-macho \
11+
// RUN: -enable-experimental-feature Embedded
12+
13+
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unrelated %s -I %t \
14+
// RUN: -swift-version 5 -target arm64-apple-none-macho \
15+
// RUN: -enable-experimental-feature Embedded
16+
17+
// REQUIRES: swift_feature_Embedded
18+
// REQUIRES: embedded_stdlib_cross_compiling
19+
20+
@_implementationOnly internal import directs
21+
// expected-warning @-1 {{using '@_implementationOnly' without enabling library evolution for 'main' may lead to instability during execution}}
22+
// expected-note @-2 11 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
23+
// expected-note @-3 6 {{initializer 'init()' imported as 'internal' from 'directs' here}}
24+
import indirects
25+
26+
internal func localInternalFunc() {} // expected-note {{global function 'localInternalFunc()' is not '@usableFromInline' or public}}
27+
28+
@inlinable
29+
public func explicitlyInlinable(arg: StructFromDirect = StructFromDirect()) {
30+
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
31+
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
32+
// expected-error @-3 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
33+
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
34+
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
35+
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
36+
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
37+
38+
if (true) {
39+
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
40+
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
41+
}
42+
43+
func nested() {
44+
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
45+
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
46+
}
47+
nested()
48+
49+
localInternalFunc() // expected-error {{global function 'localInternalFunc()' is internal and cannot be referenced from an '@inlinable' function}}
50+
51+
explicitlyInlinable()
52+
implicitlyInlinablePublic()
53+
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is private and cannot be referenced from an '@inlinable' function}}
54+
explicitNonInliable()
55+
}
56+
57+
public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()) {
58+
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
59+
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
60+
// expected-error @-3 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
61+
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
62+
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
63+
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
64+
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
65+
66+
if (true) {
67+
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
68+
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
69+
}
70+
71+
func nested() {
72+
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
73+
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
74+
}
75+
nested()
76+
77+
localInternalFunc()
78+
79+
explicitlyInlinable()
80+
implicitlyInlinablePublic()
81+
implicitlyInlinablePrivate()
82+
explicitNonInliable()
83+
}
84+
85+
private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
86+
// expected-error @-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
87+
// expected-note @-2 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
88+
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
89+
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
90+
91+
if (true) {
92+
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
93+
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
94+
}
95+
96+
func nested() {
97+
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
98+
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
99+
}
100+
nested()
101+
102+
localInternalFunc()
103+
104+
explicitlyInlinable()
105+
implicitlyInlinablePublic()
106+
implicitlyInlinablePrivate()
107+
explicitNonInliable()
108+
}
109+
110+
@_neverEmitIntoClient
111+
public func explicitNonInliable(arg: StructFromDirect = StructFromDirect()) {
112+
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
113+
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
114+
// expected-error @-3 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
115+
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
116+
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
117+
_ = StructFromDirect()
118+
119+
if (true) {
120+
_ = StructFromDirect()
121+
}
122+
123+
@_neverEmitIntoClient
124+
func nested() {
125+
_ = StructFromDirect()
126+
}
127+
nested()
128+
129+
localInternalFunc()
130+
131+
explicitlyInlinable()
132+
implicitlyInlinablePublic()
133+
implicitlyInlinablePrivate()
134+
explicitNonInliable()
135+
}
136+
137+
@_neverEmitIntoClient
138+
internal func explicitNonInliableInternal(arg: StructFromDirect = StructFromDirect()) {
139+
_ = StructFromDirect()
140+
141+
if (true) {
142+
_ = StructFromDirect()
143+
}
144+
145+
@_neverEmitIntoClient
146+
func nested() {
147+
_ = StructFromDirect()
148+
}
149+
nested()
150+
151+
localInternalFunc()
152+
153+
explicitlyInlinable()
154+
implicitlyInlinablePublic()
155+
implicitlyInlinablePrivate()
156+
explicitNonInliable()
157+
}
158+
159+
public func legalAccessToIndirect(arg: StructFromIndirect = StructFromIndirect()) {
160+
_ = StructFromIndirect()
161+
162+
if (true) {
163+
_ = StructFromIndirect()
164+
}
165+
166+
func nested() {
167+
_ = StructFromIndirect()
168+
}
169+
nested()
170+
}
171+
172+
public struct ExposedLayoutPublic {
173+
public var publicField: StructFromDirect // expected-error {{property cannot be declared public because its type uses an internal type}}
174+
// expected-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
175+
// expected-note @-2 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
176+
177+
private var privateField: StructFromDirect
178+
}
179+
180+
private struct ExposedLayoutPrivate {
181+
private var privateField: StructFromDirect
182+
}

test/Sema/access-level-import-embedded.swift

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
// REQUIRES: swift_feature_Embedded
1818
// REQUIRES: embedded_stdlib_cross_compiling
1919

20-
@_implementationOnly internal import directs
21-
// expected-warning @-1 {{using '@_implementationOnly' without enabling library evolution for 'main' may lead to instability during execution}}
22-
// expected-note @-2 19 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
23-
// expected-note @-3 12 {{initializer 'init()' imported as 'internal' from 'directs' here}}
20+
internal import directs
21+
// expected-note @-1 11 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
22+
// expected-note @-2 6 {{initializer 'init()' imported as 'internal' from 'directs' here}}
2423
import indirects
2524

2625
internal func localInternalFunc() {} // expected-note {{global function 'localInternalFunc()' is not '@usableFromInline' or public}}
@@ -50,27 +49,23 @@ public func explicitlyInlinable(arg: StructFromDirect = StructFromDirect()) {
5049

5150
explicitlyInlinable()
5251
implicitlyInlinablePublic()
53-
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is private and cannot be referenced from an '@inlinable' function}}
52+
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is internal and cannot be referenced from an '@inlinable' function}}
5453
explicitNonInliable()
5554
}
5655

5756
public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()) {
5857
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
5958
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
60-
// expected-error @-3 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
61-
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
62-
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
63-
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
64-
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
59+
// expected-error @-3 {{function cannot be declared public because its parameter uses an internal type}}
60+
// expected-note @-4 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
61+
_ = StructFromDirect()
6562

6663
if (true) {
67-
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
68-
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
64+
_ = StructFromDirect()
6965
}
7066

7167
func nested() {
72-
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
73-
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
68+
_ = StructFromDirect()
7469
}
7570
nested()
7671

@@ -82,20 +77,16 @@ public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()
8277
explicitNonInliable()
8378
}
8479

85-
private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
86-
// expected-error @-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
87-
// expected-note @-2 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
88-
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
89-
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
80+
internal func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
81+
// expected-note @-1 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
82+
_ = StructFromDirect()
9083

9184
if (true) {
92-
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
93-
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
85+
_ = StructFromDirect()
9486
}
9587

9688
func nested() {
97-
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
98-
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
89+
_ = StructFromDirect()
9990
}
10091
nested()
10192

@@ -111,9 +102,8 @@ private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect
111102
public func explicitNonInliable(arg: StructFromDirect = StructFromDirect()) {
112103
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
113104
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
114-
// expected-error @-3 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
115-
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
116-
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
105+
// expected-error @-3 {{function cannot be declared public because its parameter uses an internal type}}
106+
// expected-note @-4 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
117107
_ = StructFromDirect()
118108

119109
if (true) {
@@ -171,12 +161,11 @@ public func legalAccessToIndirect(arg: StructFromIndirect = StructFromIndirect()
171161

172162
public struct ExposedLayoutPublic {
173163
public var publicField: StructFromDirect // expected-error {{property cannot be declared public because its type uses an internal type}}
174-
// expected-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
175-
// expected-note @-2 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
164+
// expected-note @-1 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
176165

177-
private var privateField: StructFromDirect
166+
internal var privateField: StructFromDirect
178167
}
179168

180-
private struct ExposedLayoutPrivate {
181-
private var privateField: StructFromDirect
169+
internal struct ExposedLayoutPrivate {
170+
internal var privateField: StructFromDirect
182171
}

0 commit comments

Comments
 (0)