Skip to content

Commit 8eb530c

Browse files
committed
Sema: Accept @_implementationOnly protocols
1 parent a604d99 commit 8eb530c

File tree

3 files changed

+170
-20
lines changed

3 files changed

+170
-20
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient,
474474
83)
475475

476476
SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly,
477-
OnImport | OnFunc | OnConstructor | OnVar | OnSubscript | OnStruct | OnClass | OnEnum,
477+
OnImport | OnFunc | OnConstructor | OnVar | OnSubscript | OnNominalType,
478478
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr,
479479
84)
480480

lib/Sema/TypeCheckAccess.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,13 +2163,12 @@ swift::getDisallowedOriginKind(const Decl *decl,
21632163
Feature::AssumeResilientCxxTypes))
21642164
return DisallowedOriginKind::FragileCxxAPI;
21652165

2166-
if (isa<StructDecl>(decl) || isa<EnumDecl>(decl)) {
2167-
if (decl->getASTContext().LangOpts.hasFeature(
2168-
Feature::CheckImplementationOnly) &&
2169-
decl->getAttrs().hasAttribute<ImplementationOnlyAttr>()) {
2170-
return DisallowedOriginKind::ImplementationOnlyMemoryLayout;
2171-
}
2172-
}
2166+
// Implementation-only memory layouts for non-library-evolution mode.
2167+
if (isa<NominalTypeDecl>(decl) &&
2168+
decl->getASTContext().LangOpts.hasFeature(
2169+
Feature::CheckImplementationOnly) &&
2170+
decl->getAttrs().hasAttribute<ImplementationOnlyAttr>())
2171+
return DisallowedOriginKind::ImplementationOnlyMemoryLayout;
21732172

21742173
// Report non-public import last as it can be ignored by the caller.
21752174
// See \c diagnoseValueDeclRefExportability.

test/Sema/hidden-memory-layout.swift

Lines changed: 163 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,33 @@ private enum HiddenEnum {
118118
}
119119
#endif
120120

121+
public protocol ExposedProtocolPublic {
122+
}
123+
124+
internal protocol ExposedProtocolInternal {
125+
// expected-note @-1 {{protocol 'ExposedProtocolInternal' is not '@usableFromInline' or public}}
126+
// expected-note @-2 {{type declared here}}
127+
}
128+
129+
private protocol ExposedProtocolPrivate {
130+
// expected-note @-1 {{protocol 'ExposedProtocolPrivate' is not '@usableFromInline' or public}}
131+
// expected-note @-2 2 {{type declared here}}
132+
}
133+
134+
#if UseImplementationOnly
135+
@_implementationOnly
136+
private protocol HiddenProtocol {
137+
// expected-opt-in-note @-1 {{protocol 'HiddenProtocol' is not '@usableFromInline' or public}}
138+
// expected-opt-in-note @-2 9 {{protocol declared here}}
139+
// expected-opt-in-note @-3 2 {{type declared here}}
140+
}
141+
#else
142+
private protocol HiddenProtocol {
143+
// expected-not-opt-in-note @-1 1 {{protocol 'HiddenProtocol' is not '@usableFromInline' or public}}
144+
// expected-not-opt-in-note @-2 2 {{type declared here}}
145+
}
146+
#endif
147+
121148
/// Function use sites
122149

123150
@inlinable
@@ -138,6 +165,14 @@ public func explicitlyInlinable() {
138165
let _: HiddenEnum = HiddenEnum.A
139166
// expected-error @-1 2 {{enum 'HiddenEnum' is private and cannot be referenced from an '@inlinable' function}}
140167
// expected-error @-2 {{enum case 'A' is private and cannot be referenced from an '@inlinable' function}}
168+
169+
let _: ExposedProtocolPublic
170+
let _: ExposedProtocolInternal
171+
// expected-error @-1 {{protocol 'ExposedProtocolInternal' is internal and cannot be referenced from an '@inlinable' function}}
172+
let _: ExposedProtocolPrivate
173+
// expected-error @-1 {{protocol 'ExposedProtocolPrivate' is private and cannot be referenced from an '@inlinable' function}}
174+
let _: HiddenProtocol
175+
// expected-error @-1 {{protocol 'HiddenProtocol' is private and cannot be referenced from an '@inlinable' function}}
141176
}
142177

143178
public func implicitlyInlinablePublic() {
@@ -150,6 +185,12 @@ public func implicitlyInlinablePublic() {
150185
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
151186
let _: HiddenEnum = HiddenEnum.A
152187
// expected-embedded-opt-in-error @-1 2 {{enum 'HiddenEnum' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenEnum' is marked '@_implementationOnly'}}
188+
189+
let _: ExposedProtocolPublic
190+
let _: ExposedProtocolInternal
191+
let _: ExposedProtocolPrivate
192+
let _: HiddenProtocol
193+
// expected-embedded-opt-in-error @-1 {{protocol 'HiddenProtocol' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenProtocol' is marked '@_implementationOnly'}}
153194
}
154195

155196
private func implicitlyInlinablePrivate() {
@@ -162,6 +203,12 @@ private func implicitlyInlinablePrivate() {
162203
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
163204
let _: HiddenEnum = HiddenEnum.A
164205
// expected-embedded-opt-in-error @-1 2 {{enum 'HiddenEnum' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenEnum' is marked '@_implementationOnly'}}
206+
207+
let _: ExposedProtocolPublic
208+
let _: ExposedProtocolInternal
209+
let _: ExposedProtocolPrivate
210+
let _: HiddenProtocol
211+
// expected-embedded-opt-in-error @-1 {{protocol 'HiddenProtocol' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenProtocol' is marked '@_implementationOnly'}}
165212
}
166213

167214
@export(interface)
@@ -172,6 +219,11 @@ public func explicitNonInliable() {
172219
let _: ExposedEnumPublic = ExposedEnumPublic.A
173220
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
174221
let _: HiddenEnum = HiddenEnum.A
222+
223+
let _: ExposedProtocolPublic
224+
let _: ExposedProtocolInternal
225+
let _: ExposedProtocolPrivate
226+
let _: HiddenProtocol
175227
}
176228

177229
@export(interface)
@@ -182,6 +234,11 @@ internal func explicitNonInliableInternal() {
182234
let _: ExposedEnumPublic = ExposedEnumPublic.A
183235
let _: ExposedEnumPrivate = ExposedEnumPrivate.A
184236
let _: HiddenEnum = HiddenEnum.A
237+
238+
let _: ExposedProtocolPublic
239+
let _: ExposedProtocolInternal
240+
let _: ExposedProtocolPrivate
241+
let _: HiddenProtocol
185242
}
186243

187244
/// Struct use sites
@@ -198,7 +255,6 @@ public struct ExposedLayoutPublicUser: ProtocolFromDirect {
198255
private var a: ExposedLayoutPublic
199256
private var aa: ExposedLayoutInternal
200257
private var b: ExposedLayoutPrivate
201-
202258
private var c: HiddenLayout
203259
// 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'}}
204260

@@ -207,6 +263,15 @@ public struct ExposedLayoutPublicUser: ProtocolFromDirect {
207263
private var f: HiddenEnum
208264
// 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'}}
209265

266+
private var pp: ProtocolFromDirect
267+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
268+
269+
private var g: ExposedProtocolPublic
270+
private var h: ExposedProtocolInternal
271+
private var i: ExposedProtocolPrivate
272+
private var j: HiddenProtocol
273+
// expected-opt-in-error @-1 {{cannot use protocol 'HiddenProtocol' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenProtocol' is marked '@_implementationOnly'}}
274+
210275
private func privateFunc(h: HiddenLayout) {}
211276
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenLayout' is marked '@_implementationOnly'}}
212277
}
@@ -228,6 +293,12 @@ internal struct ExposedLayoutInternalUser: ProtocolFromDirect {
228293
private var f: HiddenEnum
229294
// 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'}}
230295

296+
private var g: ExposedProtocolPublic
297+
private var h: ExposedProtocolInternal
298+
private var i: ExposedProtocolPrivate
299+
private var j: HiddenProtocol
300+
// expected-opt-in-error @-1 {{cannot use protocol 'HiddenProtocol' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenProtocol' is marked '@_implementationOnly'}}
301+
231302
private func privateFunc(h: HiddenLayout) {}
232303
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenLayout' is marked '@_implementationOnly'}}
233304
}
@@ -249,6 +320,12 @@ private struct ExposedLayoutPrivateUser: ProtocolFromDirect {
249320
private var f: HiddenEnum
250321
// 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'}}
251322

323+
private var g: ExposedProtocolPublic
324+
private var h: ExposedProtocolInternal
325+
private var i: ExposedProtocolPrivate
326+
private var j: HiddenProtocol
327+
// expected-opt-in-error @-1 {{cannot use protocol 'HiddenProtocol' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenProtocol' is marked '@_implementationOnly'}}
328+
252329
private func privateFunc(h: HiddenLayout) {}
253330
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenLayout' is marked '@_implementationOnly'}}
254331
}
@@ -261,50 +338,75 @@ private struct HiddenLayoutUser {
261338
private var a: ExposedLayoutPublic
262339
private var aa: ExposedLayoutInternal
263340
private var b: ExposedLayoutPrivate
341+
264342
private var c: HiddenLayout
265343
private var d: ExposedEnumPublic
266344
private var e: ExposedEnumPrivate
267345
private var f: HiddenEnum
268346

347+
private var g: ExposedProtocolPublic
348+
private var h: ExposedProtocolInternal
349+
private var i: ExposedProtocolPrivate
350+
private var j: HiddenProtocol
351+
269352
@export(interface)
270353
private func privateFunc(h: HiddenLayout) {}
271354
}
272355

273356
@_implementationOnly // expected-opt-in-error {{'@_implementationOnly' may not be used on public declarations}}
274357
public struct PublicHiddenStruct {}
275358

276-
277359
#endif
278360

279361
/// Enums use sites
280362

281363
public enum PublicEnumUser: ProtocolFromDirect {
282364
// expected-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
283365
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'}}
366+
367+
case e(ExposedLayoutPublic)
286368
case c(ExposedLayoutInternal) // expected-error {{enum case in a public enum uses an internal type}}
287369
case d(ExposedLayoutPrivate) // expected-error {{enum case in a public enum uses a private type}}
288-
case e(ExposedLayoutPublic)
370+
case b(HiddenLayout) // expected-error {{enum case in a public enum uses a private type}}
371+
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' here; 'HiddenLayout' is marked '@_implementationOnly'}}
372+
373+
case f(ExposedProtocolPublic)
374+
case g(ExposedProtocolInternal) // expected-error {{enum case in a public enum uses an internal type}}
375+
case h(ExposedProtocolPrivate) // expected-error {{enum case in a public enum uses a private type}}
376+
case i(HiddenProtocol) // expected-opt-in-error {{cannot use protocol 'HiddenProtocol' here; 'HiddenProtocol' is marked '@_implementationOnly'}}
377+
// expected-error @-1 {{enum case in a public enum uses a private type}}
289378
}
290379

291380
internal enum InternalEnumUser: ProtocolFromDirect {
292381
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
293382
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}}
383+
384+
case e(ExposedLayoutPublic)
296385
case c(ExposedLayoutInternal)
297386
case d(ExposedLayoutPrivate) // expected-error {{enum case in an internal enum uses a private type}}
298-
case e(ExposedLayoutPublic)
387+
case b(HiddenLayout) // expected-opt-in-error {{cannot use struct 'HiddenLayout' here; 'HiddenLayout' is marked '@_implementationOnly'}}
388+
// expected-error @-1 {{enum case in an internal enum uses a private type}}
389+
390+
case f(ExposedProtocolPublic)
391+
case g(ExposedProtocolInternal)
392+
case h(ExposedProtocolPrivate) // expected-error {{enum case in an internal enum uses a private type}}
393+
case i(HiddenProtocol) // expected-opt-in-error {{cannot use protocol 'HiddenProtocol' here; 'HiddenProtocol' is marked '@_implementationOnly'}}
394+
// expected-error @-1 {{enum case in an internal enum uses a private type}}
299395
}
300396

301397
private enum PrivateEnumUser: ProtocolFromDirect {
302398
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' in a public or '@usableFromInline' conformance; 'directs' has been imported as implementation-only}}
303399
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'}}
400+
401+
case e(ExposedLayoutPublic)
305402
case c(ExposedLayoutInternal)
306403
case d(ExposedLayoutPrivate)
307-
case e(ExposedLayoutPublic)
404+
case b(HiddenLayout) // expected-opt-in-error {{cannot use struct 'HiddenLayout' here; 'HiddenLayout' is marked '@_implementationOnly'}}
405+
406+
case f(ExposedProtocolPublic)
407+
case g(ExposedProtocolInternal)
408+
case h(ExposedProtocolPrivate)
409+
case i(HiddenProtocol) // expected-opt-in-error {{cannot use protocol 'HiddenProtocol' here; 'HiddenProtocol' is marked '@_implementationOnly'}}
308410
}
309411

310412
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}}
@@ -316,10 +418,16 @@ internal enum InternalEnumWithRawType : RawTypeFromDirect { // expected-opt-in-e
316418
@_implementationOnly
317419
private enum PrivateHiddenEnumUser: ProtocolFromDirect {
318420
case a(StructFromDirect)
319-
case b(HiddenLayout)
421+
422+
case e(ExposedLayoutPublic)
320423
case c(ExposedLayoutInternal)
321424
case d(ExposedLayoutPrivate)
322-
case e(ExposedLayoutPublic)
425+
case b(HiddenLayout)
426+
427+
case f(ExposedProtocolPublic)
428+
case g(ExposedProtocolInternal)
429+
case h(ExposedProtocolPrivate)
430+
case i(HiddenProtocol)
323431
}
324432

325433
@_implementationOnly // expected-opt-in-error {{'@_implementationOnly' may not be used on public declarations}}
@@ -356,6 +464,12 @@ public class PublicClass: ProtocolFromDirect {
356464
private var f: HiddenEnum
357465
// 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'}}
358466

467+
private var g: ExposedProtocolPublic
468+
private var h: ExposedProtocolInternal
469+
private var i: ExposedProtocolPrivate
470+
private var j: HiddenProtocol
471+
// expected-opt-in-error @-1 {{cannot use protocol 'HiddenProtocol' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenProtocol' is marked '@_implementationOnly'}}
472+
359473
@export(interface)
360474
private func privateFunc(h: HiddenLayout) {}
361475
}
@@ -381,6 +495,12 @@ internal class InternalClass: ProtocolFromDirect {
381495
private var f: HiddenEnum
382496
// 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'}}
383497

498+
private var g: ExposedProtocolPublic
499+
private var h: ExposedProtocolInternal
500+
private var i: ExposedProtocolPrivate
501+
private var j: HiddenProtocol
502+
// expected-opt-in-error @-1 {{cannot use protocol 'HiddenProtocol' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenProtocol' is marked '@_implementationOnly'}}
503+
384504
private func privateFunc(h: HiddenLayout) {} // expected-embedded-opt-in-error {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenLayout' is marked '@_implementationOnly'}}
385505
}
386506

@@ -405,6 +525,12 @@ private class PrivateClass: ProtocolFromDirect {
405525
private var f: HiddenEnum
406526
// 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'}}
407527

528+
private var g: ExposedProtocolPublic
529+
private var h: ExposedProtocolInternal
530+
private var i: ExposedProtocolPrivate
531+
private var j: HiddenProtocol
532+
// expected-opt-in-error @-1 {{cannot use protocol 'HiddenProtocol' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'HiddenProtocol' is marked '@_implementationOnly'}}
533+
408534
private func privateFunc(h: HiddenLayout) {} // expected-embedded-opt-in-error {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@export(interface)' because 'HiddenLayout' is marked '@_implementationOnly'}}
409535
}
410536

@@ -424,8 +550,33 @@ internal class HiddenClass: ProtocolFromDirect {
424550
private var d: ExposedEnumPublic
425551
private var e: ExposedEnumPrivate
426552
private var f: HiddenEnum
553+
554+
private var g: ExposedProtocolPublic
555+
private var h: ExposedProtocolInternal
556+
private var i: ExposedProtocolPrivate
557+
private var j: HiddenProtocol
427558
}
428559

429560
@_implementationOnly // expected-opt-in-error {{'@_implementationOnly' may not be used on public declarations}}
430561
public enum PublicHiddenClass {}
431562
#endif
563+
564+
/// Protocol use sites
565+
566+
public protocol PublicProtocol : ProtocolFromDirect {
567+
// expected-error @-1 {{cannot use protocol 'ProtocolFromDirect' here; 'directs' has been imported as implementation-only}}
568+
}
569+
570+
internal protocol InternalProtocol : ProtocolFromDirect {
571+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' here; 'directs' has been imported as implementation-only}}
572+
}
573+
574+
private protocol PrivateProtocol : ProtocolFromDirect {
575+
// expected-opt-in-error @-1 {{cannot use protocol 'ProtocolFromDirect' here; 'directs' has been imported as implementation-only}}
576+
}
577+
578+
#if UseImplementationOnly
579+
@_implementationOnly
580+
internal protocol PrivateProtocolHidden : ProtocolFromDirect {
581+
}
582+
#endif

0 commit comments

Comments
 (0)