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
This commit is contained in:
Ellie Shin
2024-04-18 16:23:19 -07:00
parent 70afeef480
commit 573d1b96ca
4 changed files with 167 additions and 14 deletions

View File

@@ -6794,18 +6794,18 @@ WARNING(discardable_result_on_void_never_function, none,
//------------------------------------------------------------------------------
ERROR(fixed_layout_attr_on_internal_type,
none, "'@_fixed_layout' attribute can only be applied to '@usableFromInline' "
"or public declarations, but %0 is "
"%select{private|fileprivate|internal|package|%error|%error}1",
none, "'@_fixed_layout' attribute can only be applied to '@usableFromInline', "
"package, or public declarations, but %0 is "
"%select{private|fileprivate|internal|%error|%error|%error}1",
(DeclName, AccessLevel))
WARNING(fixed_layout_struct,
none, "'@frozen' attribute is now used for fixed-layout structs", ())
ERROR(frozen_attr_on_internal_type,
none, "'@frozen' attribute can only be applied to '@usableFromInline' "
"or public declarations, but %0 is "
"%select{private|fileprivate|internal|package|%error|%error}1",
none, "'@frozen' attribute can only be applied to '@usableFromInline', "
"package, or public declarations, but %0 is "
"%select{private|fileprivate|internal|%error|%error|%error}1",
(DeclName, AccessLevel))
ERROR(usable_from_inline_attr_with_explicit_access,
@@ -6897,8 +6897,8 @@ ERROR(inlinable_dynamic_not_supported,
none, "'@inlinable' attribute cannot be applied to 'dynamic' declarations", ())
ERROR(inlinable_decl_not_public,
none, "'@inlinable' attribute can only be applied to public declarations, "
"but %0 is %select{private|fileprivate|internal|package|%error|%error}1",
none, "'@inlinable' attribute can only be applied to package or public declarations, "
"but %0 is %select{private|fileprivate|internal|%error|%error|%error}1",
(DeclBaseName, AccessLevel))
ERROR(inlinable_resilient_deinit,

View File

@@ -3168,7 +3168,7 @@ void AttributeChecker::visitFixedLayoutAttr(FixedLayoutAttr *attr) {
auto *VD = cast<ValueDecl>(D);
if (VD->getFormalAccess() < AccessLevel::Public &&
if (VD->getFormalAccess() < AccessLevel::Package &&
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
diagnoseAndRemoveAttr(attr, diag::fixed_layout_attr_on_internal_type,
VD->getName(), VD->getFormalAccess());
@@ -3227,7 +3227,8 @@ void AttributeChecker::visitInlinableAttr(InlinableAttr *attr) {
return;
}
// @inlinable can only be applied to public or internal declarations.
// @inlinable can only be applied to public, package, or
// internal declarations.
auto access = VD->getFormalAccess();
if (access < AccessLevel::Internal) {
diagnoseAndRemoveAttr(attr, diag::inlinable_decl_not_public,
@@ -3934,7 +3935,7 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
return;
}
if (ED->getFormalAccess() < AccessLevel::Public &&
if (ED->getFormalAccess() < AccessLevel::Package &&
!ED->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
diagnoseAndRemoveAttr(attr, diag::enum_frozen_nonpublic, attr);
return;
@@ -3943,7 +3944,9 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
auto *VD = cast<ValueDecl>(D);
if (VD->getFormalAccess() < AccessLevel::Public &&
// @frozen attribute is allowed for public, package, or
// usableFromInline decls.
if (VD->getFormalAccess() < AccessLevel::Package &&
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
diagnoseAndRemoveAttr(attr, diag::frozen_attr_on_internal_type,
VD->getName(), VD->getFormalAccess());

View File

@@ -0,0 +1,44 @@
// RUN: %target-swift-frontend -typecheck %s -I %t -swift-version 5 -package-name mypkg -verify
package struct PkgStruct {
package var one: Int
package var two: String
package func f() {}
}
@frozen
package struct FrozenPkgStruct {
package var one: Int
package var two: String
package func f() {}
}
@frozen
@usableFromInline
package struct FrozenUfiPkgStruct {
package var one: Int
package var two: String
package func f() {}
}
@frozen // expected-error {{'@frozen' attribute can only be applied to '@usableFromInline', package, or public declarations, but 'FrozenInternalStruct' is internal}} {{1-9=}}
struct FrozenInternalStruct {
var one: Int
var two: String
func f() {}
}
@_fixed_layout
package class FixedPkgKlass {
package var one: Int = 1
package var two: String = ""
package func f() {}
}
@_fixed_layout // expected-error {{'@_fixed_layout' attribute can only be applied to '@usableFromInline', package, or public declarations, but 'FixedInternalKlass' is internal}} {{1-16=}}
class FixedInternalKlass {
var one: Int = 1
var two: String = ""
func f() {}
}

View File

@@ -8,6 +8,8 @@
// RUN: -experimental-allow-non-resilient-access \
// RUN: -emit-module -emit-module-path %t/Utils.swiftmodule
// RUN: %target-swift-frontend -typecheck %t/Utils.swift -I %t -swift-version 5 -package-name mypkg -verify
// RUN: %target-swift-frontend -typecheck %t/ClientDefault.swift -I %t -swift-version 5 -package-name mypkg -verify
// 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 {
case two(Int)
}
@frozen
package enum FrozenPkgEnum {
case one
case two(Int)
}
@frozen
@usableFromInline
package enum FrozenUfiPkgEnum {
case one
case two(Int)
}
@usableFromInline
package enum UfiPkgEnum {
case one
@@ -36,6 +51,61 @@ public enum FrozenPublicEnum {
case two(Int)
}
package func uf(_ arg: PkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func um(_ arg: FrozenPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func un(_ arg: FrozenUfiPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func ug(_ arg: UfiPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
public func uh(_ arg: PublicEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
public func uk(_ arg: FrozenPublicEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
//--- ClientDefault.swift
import Utils
@@ -48,6 +118,24 @@ package func f(_ arg: PkgEnum) -> Int {
}
}
package func m(_ arg: FrozenPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func n(_ arg: FrozenUfiPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func g(_ arg: UfiPkgEnum) -> Int {
switch arg { // expected-warning {{switch covers known cases, but 'UfiPkgEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
case .one:
@@ -80,8 +168,8 @@ public func k(_ arg: FrozenPublicEnum) -> Int {
import Utils
// With optimization enabled to bypass resilience checks within
// a package boundary, public (non-frozen) or package enums no
// longer require `@unknown default` in source code switch stmts.
// a package boundary, public (non-frozen) or package (non-frozen)
// enums no longer require `@unknown default` in switch stmts.
package func f(_ arg: PkgEnum) -> Int {
switch arg { // no-warning
case .one:
@@ -91,6 +179,24 @@ package func f(_ arg: PkgEnum) -> Int {
}
}
package func m(_ arg: FrozenPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func n(_ arg: FrozenUfiPkgEnum) -> Int {
switch arg { // no-warning
case .one:
return 1
case .two(let val):
return 2 + val
}
}
package func g(_ arg: UfiPkgEnum) -> Int {
switch arg { // no-warning
case .one: