Skip to content

Commit b107169

Browse files
committed
Sema: Exportability check super types
1 parent 8567630 commit b107169

File tree

3 files changed

+152
-9
lines changed

3 files changed

+152
-9
lines changed

lib/AST/Availability.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,19 @@ bool swift::isExported(const ValueDecl *VD) {
10091009
if (property->isLayoutExposedToClients(/*applyImplicit=*/true))
10101010
return true;
10111011

1012+
// Is this a type exposed by default in a non-resilient module?
1013+
if (isa<NominalTypeDecl>(VD) &&
1014+
VD->getASTContext().LangOpts.hasFeature(
1015+
Feature::CheckImplementationOnly) &&
1016+
VD->getDeclContext()->getParentModule()->getResilienceStrategy() !=
1017+
ResilienceStrategy::Resilient &&
1018+
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
1019+
return true;
1020+
1021+
// Case of an enum not marked @_implementationOnly in a non-resilient module?
1022+
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
1023+
return isExported(EED->getParentEnum());
1024+
10121025
return false;
10131026
}
10141027

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,10 @@ extension StructFromIndirect {
2929
set {}
3030
}
3131
}
32+
33+
public struct RawTypeFromDirect : Equatable, ExpressibleByIntegerLiteral {
34+
public typealias IntegerLiteralType = Int
35+
public init(integerLiteral: Int) {}
36+
}
37+
38+
public protocol ProtocolFromDirect { }

test/Sema/hidden-memory-layout.swift

Lines changed: 132 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ public struct ExposedLayoutPublic {
6363
}
6464

6565
internal struct ExposedLayoutInternal {
66+
// expected-note @-1 {{type declared here}}
6667
}
6768

6869
private struct ExposedLayoutPrivate {
6970
// expected-note @-1 2 {{struct 'ExposedLayoutPrivate' is not '@usableFromInline' or public}}
71+
// expected-note @-2 2 {{type declared here}}
7072
init() { fatalError() } // expected-note {{initializer 'init()' is not '@usableFromInline' or public}}
7173
}
7274

@@ -75,13 +77,14 @@ private struct ExposedLayoutPrivate {
7577
private struct HiddenLayout {
7678
// expected-opt-in-note @-1 2 {{struct 'HiddenLayout' is not '@usableFromInline' or public}}
7779
// expected-opt-in-note @-2 1 {{initializer 'init()' is not '@usableFromInline' or public}}
78-
// expected-opt-in-note @-3 2 {{struct declared here}}
79-
// expected-opt-in-note @-4 4 {{struct declared here}}
80+
// expected-opt-in-note @-3 9 {{struct declared here}}
81+
// expected-opt-in-note @-4 2 {{type declared here}}
8082
}
8183
#else
8284
private struct HiddenLayout {
8385
// expected-not-opt-in-note @-1 2 {{struct 'HiddenLayout' is not '@usableFromInline' or public}}
8486
// expected-not-opt-in-note @-2 1 {{initializer 'init()' is not '@usableFromInline' or public}}
87+
// expected-not-opt-in-note @-3 2 {{type declared here}}
8588
}
8689
#endif
8790

@@ -97,6 +100,24 @@ private enum ExposedEnumPrivate {
97100
case B
98101
}
99102

103+
#if UseImplementationOnly
104+
@_implementationOnly
105+
private enum HiddenEnum {
106+
// expected-opt-in-note @-1 6 {{enum declared here}}
107+
// expected-opt-in-note @-2 2 {{enum 'HiddenEnum' is not '@usableFromInline' or public}}
108+
case A
109+
// expected-opt-in-note @-1 {{enum case 'A' is not '@usableFromInline' or public}}
110+
case B
111+
}
112+
#else
113+
private enum HiddenEnum {
114+
// expected-not-opt-in-note @-1 2 {{enum 'HiddenEnum' is not '@usableFromInline' or public}}
115+
case A
116+
// expected-not-opt-in-note @-1 {{enum case 'A' is not '@usableFromInline' or public}}
117+
case B
118+
}
119+
#endif
120+
100121
/// Function use sites
101122

102123
@inlinable
@@ -114,6 +135,9 @@ public func explicitlyInlinable() {
114135
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
115136
// expected-error @-1 2 {{enum 'ExposedEnumPrivate' is private and cannot be referenced from an '@inlinable' function}}
116137
// expected-error @-2 {{enum case 'A' is private and cannot be referenced from an '@inlinable' function}}
138+
let _: HiddenEnum = HiddenEnum.A
139+
// expected-error @-1 2 {{enum 'HiddenEnum' is private and cannot be referenced from an '@inlinable' function}}
140+
// expected-error @-2 {{enum case 'A' is private and cannot be referenced from an '@inlinable' function}}
117141
}
118142

119143
public func implicitlyInlinablePublic() {
@@ -124,6 +148,8 @@ public func implicitlyInlinablePublic() {
124148

125149
let _: ExposedEnumPublic = ExposedEnumPublic.A
126150
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
151+
let _: HiddenEnum = HiddenEnum.A
152+
// expected-embedded-opt-in-error @-1 2 {{enum 'HiddenEnum' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenEnum' is marked '@_implementationOnly'}}
127153
}
128154

129155
private func implicitlyInlinablePrivate() {
@@ -134,6 +160,8 @@ private func implicitlyInlinablePrivate() {
134160

135161
let _: ExposedEnumPublic = ExposedEnumPublic.A
136162
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
163+
let _: HiddenEnum = HiddenEnum.A
164+
// expected-embedded-opt-in-error @-1 2 {{enum 'HiddenEnum' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenEnum' is marked '@_implementationOnly'}}
137165
}
138166

139167
@_neverEmitIntoClient
@@ -143,6 +171,7 @@ public func explicitNonInliable() {
143171
let _: HiddenLayout = HiddenLayout()
144172
let _: ExposedEnumPublic = ExposedEnumPublic.A
145173
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
174+
let _: HiddenEnum = HiddenEnum.A
146175
}
147176

148177
@_neverEmitIntoClient
@@ -152,11 +181,13 @@ internal func explicitNonInliableInternal() {
152181
let _: HiddenLayout = HiddenLayout()
153182
let _: ExposedEnumPublic = ExposedEnumPublic.A
154183
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
184+
let _: HiddenEnum = HiddenEnum.A
155185
}
156186

157187
/// Struct use sites
158188

159-
public struct ExposedLayoutPublicUser {
189+
public struct ExposedLayoutPublicUser: ProtocolFromDirect {
190+
// expected-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
160191

161192
public var publicField: StructFromDirect
162193
// 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}}
@@ -171,11 +202,17 @@ public struct ExposedLayoutPublicUser {
171202
private var c: HiddenLayout
172203
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenLayout' is marked '@_implementationOnly'}}
173204

205+
private var d: ExposedEnumPublic
206+
private var e: ExposedEnumPrivate
207+
private var f: HiddenEnum
208+
// expected-opt-in-error @-1 {{cannot use enum 'HiddenEnum' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenEnum' is marked '@_implementationOnly'}}
209+
174210
private func privateFunc(h: HiddenLayout) {}
175211
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenLayout' is marked '@_implementationOnly'}}
176212
}
177213

178-
internal struct ExposedLayoutInternalUser {
214+
internal struct ExposedLayoutInternalUser: ProtocolFromDirect {
215+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
179216

180217
private var privateField: StructFromDirect
181218
// expected-opt-in-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}}
@@ -186,11 +223,17 @@ internal struct ExposedLayoutInternalUser {
186223
private var c: HiddenLayout
187224
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenLayout' is marked '@_implementationOnly'}}
188225

226+
private var d: ExposedEnumPublic
227+
private var e: ExposedEnumPrivate
228+
private var f: HiddenEnum
229+
// expected-opt-in-error @-1 {{cannot use enum 'HiddenEnum' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenEnum' is marked '@_implementationOnly'}}
230+
189231
private func privateFunc(h: HiddenLayout) {}
190232
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenLayout' is marked '@_implementationOnly'}}
191233
}
192234

193-
private struct ExposedLayoutPrivateUser {
235+
private struct ExposedLayoutPrivateUser: ProtocolFromDirect {
236+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
194237

195238
private var privateField: StructFromDirect
196239
// expected-opt-in-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}}
@@ -201,6 +244,11 @@ private struct ExposedLayoutPrivateUser {
201244
private var c: HiddenLayout
202245
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenLayout' is marked '@_implementationOnly'}}
203246

247+
private var d: ExposedEnumPublic
248+
private var e: ExposedEnumPrivate
249+
private var f: HiddenEnum
250+
// expected-opt-in-error @-1 {{cannot use enum 'HiddenEnum' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenEnum' is marked '@_implementationOnly'}}
251+
204252
private func privateFunc(h: HiddenLayout) {}
205253
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenLayout' is marked '@_implementationOnly'}}
206254
}
@@ -214,18 +262,82 @@ private struct HiddenLayoutUser {
214262
private var aa: ExposedLayoutInternal
215263
private var b: ExposedLayoutPrivate
216264
private var c: HiddenLayout
265+
private var d: ExposedEnumPublic
266+
private var e: ExposedEnumPrivate
267+
private var f: HiddenEnum
217268

218269
@_neverEmitIntoClient
219270
private func privateFunc(h: HiddenLayout) {}
220271
}
221272

222273
@_implementationOnly // expected-opt-in-error {{'@_implementationOnly' may not be used on public declarations}}
223274
public struct PublicHiddenStruct {}
275+
276+
277+
#endif
278+
279+
/// Enums use sites
280+
281+
public enum PublicEnumUser: ProtocolFromDirect {
282+
// expected-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
283+
case a(StructFromDirect) // expected-error {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
284+
case b(HiddenLayout) // expected-error {{enum case in a public enum uses a private type}}
285+
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' here; 'HiddenLayout' is marked '@_implementationOnly'}}
286+
case c(ExposedLayoutInternal) // expected-error {{enum case in a public enum uses an internal type}}
287+
case d(ExposedLayoutPrivate) // expected-error {{enum case in a public enum uses a private type}}
288+
case e(ExposedLayoutPublic)
289+
}
290+
291+
internal enum InternalEnumUser: ProtocolFromDirect {
292+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
293+
case a(StructFromDirect) // expected-opt-in-error {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
294+
case b(HiddenLayout) // expected-opt-in-error {{cannot use struct 'HiddenLayout' here; 'HiddenLayout' is marked '@_implementationOnly'}}
295+
// expected-error @-1 {{enum case in an internal enum uses a private type}}
296+
case c(ExposedLayoutInternal)
297+
case d(ExposedLayoutPrivate) // expected-error {{enum case in an internal enum uses a private type}}
298+
case e(ExposedLayoutPublic)
299+
}
300+
301+
private enum PrivateEnumUser: ProtocolFromDirect {
302+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
303+
case a(StructFromDirect) // expected-opt-in-error {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
304+
case b(HiddenLayout) // expected-opt-in-error {{cannot use struct 'HiddenLayout' here; 'HiddenLayout' is marked '@_implementationOnly'}}
305+
case c(ExposedLayoutInternal)
306+
case d(ExposedLayoutPrivate)
307+
case e(ExposedLayoutPublic)
308+
}
309+
310+
internal enum InternalEnumWithRawType : RawTypeFromDirect { // expected-opt-in-error {{cannot use struct 'RawTypeFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
311+
typealias RawValue = RawTypeFromDirect
312+
case a
313+
}
314+
315+
#if UseImplementationOnly
316+
@_implementationOnly
317+
private enum PrivateHiddenEnumUser: ProtocolFromDirect {
318+
case a(StructFromDirect)
319+
case b(HiddenLayout)
320+
case c(ExposedLayoutInternal)
321+
case d(ExposedLayoutPrivate)
322+
case e(ExposedLayoutPublic)
323+
}
324+
325+
@_implementationOnly // expected-opt-in-error {{'@_implementationOnly' may not be used on public declarations}}
326+
public enum PublicHiddenEnum {}
327+
328+
@_implementationOnly
329+
internal enum InternalEnumWithRawTypeIO : RawTypeFromDirect {
330+
typealias RawValue = RawTypeFromDirect
331+
case a
332+
}
333+
224334
#endif
225335

226336
/// Classes use sites
227337

228-
public class PublicClass {
338+
public class PublicClass: ProtocolFromDirect {
339+
// expected-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
340+
229341
public init() { fatalError() }
230342

231343
public var publicField: StructFromDirect
@@ -241,12 +353,16 @@ public class PublicClass {
241353

242354
private var d: ExposedEnumPublic
243355
private var e: ExposedEnumPrivate
356+
private var f: HiddenEnum
357+
// expected-opt-in-error @-1 {{cannot use enum 'HiddenEnum' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenEnum' is marked '@_implementationOnly'}}
244358

245359
@_neverEmitIntoClient
246360
private func privateFunc(h: HiddenLayout) {}
247361
}
248362

249-
internal class InternalClass {
363+
internal class InternalClass: ProtocolFromDirect {
364+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
365+
250366
public init() { fatalError() }
251367

252368
public var publicField: StructFromDirect
@@ -262,11 +378,15 @@ internal class InternalClass {
262378

263379
private var d: ExposedEnumPublic
264380
private var e: ExposedEnumPrivate
381+
private var f: HiddenEnum
382+
// expected-opt-in-error @-1 {{cannot use enum 'HiddenEnum' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenEnum' is marked '@_implementationOnly'}}
265383

266384
private func privateFunc(h: HiddenLayout) {} // expected-embedded-opt-in-error {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenLayout' is marked '@_implementationOnly'}}
267385
}
268386

269-
private class PrivateClass {
387+
private class PrivateClass: ProtocolFromDirect {
388+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
389+
270390
public init() { fatalError() }
271391

272392
public var publicField: StructFromDirect
@@ -282,13 +402,15 @@ private class PrivateClass {
282402

283403
private var d: ExposedEnumPublic
284404
private var e: ExposedEnumPrivate
405+
private var f: HiddenEnum
406+
// expected-opt-in-error @-1 {{cannot use enum 'HiddenEnum' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenEnum' is marked '@_implementationOnly'}}
285407

286408
private func privateFunc(h: HiddenLayout) {} // expected-embedded-opt-in-error {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'HiddenLayout' is marked '@_implementationOnly'}}
287409
}
288410

289411
#if UseImplementationOnly
290412
@_implementationOnly
291-
internal class HiddenClass {
413+
internal class HiddenClass: ProtocolFromDirect {
292414
public init() { fatalError() }
293415

294416
public var publicField: StructFromDirect
@@ -301,6 +423,7 @@ internal class HiddenClass {
301423

302424
private var d: ExposedEnumPublic
303425
private var e: ExposedEnumPrivate
426+
private var f: HiddenEnum
304427
}
305428

306429
@_implementationOnly // expected-opt-in-error {{'@_implementationOnly' may not be used on public declarations}}

0 commit comments

Comments
 (0)