Skip to content

Commit c8699c8

Browse files
committed
Allow @Frozen and @_fixed_layout for package access level.
Package decls were made to be resilient at the definition site by default. By allowing the attributes to be applied to package decls, we can enable non-resilient access. Resolves rdar://125169361
1 parent dcf078a commit c8699c8

File tree

4 files changed

+167
-14
lines changed

4 files changed

+167
-14
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6777,18 +6777,18 @@ WARNING(discardable_result_on_void_never_function, none,
67776777
//------------------------------------------------------------------------------
67786778

67796779
ERROR(fixed_layout_attr_on_internal_type,
6780-
none, "'@_fixed_layout' attribute can only be applied to '@usableFromInline' "
6781-
"or public declarations, but %0 is "
6782-
"%select{private|fileprivate|internal|package|%error|%error}1",
6780+
none, "'@_fixed_layout' attribute can only be applied to '@usableFromInline', "
6781+
"package, or public declarations, but %0 is "
6782+
"%select{private|fileprivate|internal|%error|%error|%error}1",
67836783
(DeclName, AccessLevel))
67846784

67856785
WARNING(fixed_layout_struct,
67866786
none, "'@frozen' attribute is now used for fixed-layout structs", ())
67876787

67886788
ERROR(frozen_attr_on_internal_type,
6789-
none, "'@frozen' attribute can only be applied to '@usableFromInline' "
6790-
"or public declarations, but %0 is "
6791-
"%select{private|fileprivate|internal|package|%error|%error}1",
6789+
none, "'@frozen' attribute can only be applied to '@usableFromInline', "
6790+
"package, or public declarations, but %0 is "
6791+
"%select{private|fileprivate|internal|%error|%error|%error}1",
67926792
(DeclName, AccessLevel))
67936793

67946794
ERROR(usable_from_inline_attr_with_explicit_access,
@@ -6880,8 +6880,8 @@ ERROR(inlinable_dynamic_not_supported,
68806880
none, "'@inlinable' attribute cannot be applied to 'dynamic' declarations", ())
68816881

68826882
ERROR(inlinable_decl_not_public,
6883-
none, "'@inlinable' attribute can only be applied to public declarations, "
6884-
"but %0 is %select{private|fileprivate|internal|package|%error|%error}1",
6883+
none, "'@inlinable' attribute can only be applied to package or public declarations, "
6884+
"but %0 is %select{private|fileprivate|internal|%error|%error|%error}1",
68856885
(DeclBaseName, AccessLevel))
68866886

68876887
ERROR(inlinable_resilient_deinit,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3168,7 +3168,7 @@ void AttributeChecker::visitFixedLayoutAttr(FixedLayoutAttr *attr) {
31683168

31693169
auto *VD = cast<ValueDecl>(D);
31703170

3171-
if (VD->getFormalAccess() < AccessLevel::Public &&
3171+
if (VD->getFormalAccess() < AccessLevel::Package &&
31723172
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
31733173
diagnoseAndRemoveAttr(attr, diag::fixed_layout_attr_on_internal_type,
31743174
VD->getName(), VD->getFormalAccess());
@@ -3227,7 +3227,8 @@ void AttributeChecker::visitInlinableAttr(InlinableAttr *attr) {
32273227
return;
32283228
}
32293229

3230-
// @inlinable can only be applied to public or internal declarations.
3230+
// @inlinable can only be applied to public, package, or
3231+
// internal declarations.
32313232
auto access = VD->getFormalAccess();
32323233
if (access < AccessLevel::Internal) {
32333234
diagnoseAndRemoveAttr(attr, diag::inlinable_decl_not_public,
@@ -3934,7 +3935,7 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
39343935
return;
39353936
}
39363937

3937-
if (ED->getFormalAccess() < AccessLevel::Public &&
3938+
if (ED->getFormalAccess() < AccessLevel::Package &&
39383939
!ED->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
39393940
diagnoseAndRemoveAttr(attr, diag::enum_frozen_nonpublic, attr);
39403941
return;
@@ -3943,7 +3944,9 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
39433944

39443945
auto *VD = cast<ValueDecl>(D);
39453946

3946-
if (VD->getFormalAccess() < AccessLevel::Public &&
3947+
// @frozen attribute is allowed for public, package, or
3948+
// usableFromInline decls.
3949+
if (VD->getFormalAccess() < AccessLevel::Package &&
39473950
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
39483951
diagnoseAndRemoveAttr(attr, diag::frozen_attr_on_internal_type,
39493952
VD->getName(), VD->getFormalAccess());
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-swift-frontend -typecheck %s -I %t -swift-version 5 -package-name mypkg -verify
2+
3+
package struct PkgStruct {
4+
package var one: Int
5+
package var two: String
6+
package func f() {}
7+
}
8+
9+
@frozen
10+
package struct FrozenPkgStruct {
11+
package var one: Int
12+
package var two: String
13+
package func f() {}
14+
}
15+
16+
@frozen
17+
@usableFromInline
18+
package struct FrozenUfiPkgStruct {
19+
package var one: Int
20+
package var two: String
21+
package func f() {}
22+
}
23+
24+
@frozen // expected-error {{'@frozen' attribute can only be applied to '@usableFromInline', package, or public declarations, but 'FrozenInternalStruct' is internal}} {{1-9=}}
25+
struct FrozenInternalStruct {
26+
var one: Int
27+
var two: String
28+
func f() {}
29+
}
30+
31+
@_fixed_layout
32+
package class FixedPkgKlass {
33+
package var one: Int = 1
34+
package var two: String = ""
35+
package func f() {}
36+
}
37+
38+
@_fixed_layout // expected-error {{'@_fixed_layout' attribute can only be applied to '@usableFromInline', package, or public declarations, but 'FixedInternalKlass' is internal}} {{1-16=}}
39+
class FixedInternalKlass {
40+
var one: Int = 1
41+
var two: String = ""
42+
func f() {}
43+
}
44+

test/Sema/package_resilience_bypass_exhaustive_switch.swift

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// RUN: -experimental-allow-non-resilient-access \
99
// RUN: -emit-module -emit-module-path %t/Utils.swiftmodule
1010

11+
// RUN: %target-swift-frontend -typecheck %t/Utils.swift -I %t -swift-version 5 -package-name mypkg -verify
12+
1113
// RUN: %target-swift-frontend -typecheck %t/ClientDefault.swift -I %t -swift-version 5 -package-name mypkg -verify
1214

1315
// RUN: %target-swift-frontend -typecheck %t/ClientOptimized.swift -I %t -swift-version 5 -package-name mypkg -experimental-package-bypass-resilience -verify
@@ -19,6 +21,19 @@ package enum PkgEnum {
1921
case two(Int)
2022
}
2123

24+
@frozen
25+
package enum FrozenPkgEnum {
26+
case one
27+
case two(Int)
28+
}
29+
30+
@frozen
31+
@usableFromInline
32+
package enum FrozenUfiPkgEnum {
33+
case one
34+
case two(Int)
35+
}
36+
2237
@usableFromInline
2338
package enum UfiPkgEnum {
2439
case one
@@ -36,6 +51,61 @@ public enum FrozenPublicEnum {
3651
case two(Int)
3752
}
3853

54+
package func uf(_ arg: PkgEnum) -> Int {
55+
switch arg { // no-warning
56+
case .one:
57+
return 1
58+
case .two(let val):
59+
return 2 + val
60+
}
61+
}
62+
63+
package func um(_ arg: FrozenPkgEnum) -> Int {
64+
switch arg { // no-warning
65+
case .one:
66+
return 1
67+
case .two(let val):
68+
return 2 + val
69+
}
70+
}
71+
72+
package func un(_ arg: FrozenUfiPkgEnum) -> Int {
73+
switch arg { // no-warning
74+
case .one:
75+
return 1
76+
case .two(let val):
77+
return 2 + val
78+
}
79+
}
80+
81+
package func ug(_ arg: UfiPkgEnum) -> Int {
82+
switch arg { // no-warning
83+
case .one:
84+
return 1
85+
case .two(let val):
86+
return 2 + val
87+
}
88+
}
89+
90+
public func uh(_ arg: PublicEnum) -> Int {
91+
switch arg { // no-warning
92+
case .one:
93+
return 1
94+
case .two(let val):
95+
return 2 + val
96+
}
97+
}
98+
99+
public func uk(_ arg: FrozenPublicEnum) -> Int {
100+
switch arg { // no-warning
101+
case .one:
102+
return 1
103+
case .two(let val):
104+
return 2 + val
105+
}
106+
}
107+
108+
39109
//--- ClientDefault.swift
40110
import Utils
41111

@@ -48,6 +118,24 @@ package func f(_ arg: PkgEnum) -> Int {
48118
}
49119
}
50120

121+
package func m(_ arg: FrozenPkgEnum) -> Int {
122+
switch arg { // no-warning
123+
case .one:
124+
return 1
125+
case .two(let val):
126+
return 2 + val
127+
}
128+
}
129+
130+
package func n(_ arg: FrozenUfiPkgEnum) -> Int {
131+
switch arg { // no-warning
132+
case .one:
133+
return 1
134+
case .two(let val):
135+
return 2 + val
136+
}
137+
}
138+
51139
package func g(_ arg: UfiPkgEnum) -> Int {
52140
switch arg { // expected-warning {{switch covers known cases, but 'UfiPkgEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
53141
case .one:
@@ -80,8 +168,8 @@ public func k(_ arg: FrozenPublicEnum) -> Int {
80168
import Utils
81169

82170
// With optimization enabled to bypass resilience checks within
83-
// a package boundary, public (non-frozen) or package enums no
84-
// longer require `@unknown default` in source code switch stmts.
171+
// a package boundary, public (non-frozen) or package (non-frozen)
172+
// enums no longer require `@unknown default` in switch stmts.
85173
package func f(_ arg: PkgEnum) -> Int {
86174
switch arg { // no-warning
87175
case .one:
@@ -91,6 +179,24 @@ package func f(_ arg: PkgEnum) -> Int {
91179
}
92180
}
93181

182+
package func m(_ arg: FrozenPkgEnum) -> Int {
183+
switch arg { // no-warning
184+
case .one:
185+
return 1
186+
case .two(let val):
187+
return 2 + val
188+
}
189+
}
190+
191+
package func n(_ arg: FrozenUfiPkgEnum) -> Int {
192+
switch arg { // no-warning
193+
case .one:
194+
return 1
195+
case .two(let val):
196+
return 2 + val
197+
}
198+
}
199+
94200
package func g(_ arg: UfiPkgEnum) -> Int {
95201
switch arg { // no-warning
96202
case .one:

0 commit comments

Comments
 (0)