mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Make NS_ENUM &c. Sendable even when audited
An explicit swift_attr("@_nonSendable") will override it (except for ns_error_domain where the type is embedded in another type that's forced to be Sendable), but swift_attr("@_nonSendable(_assumed)") will not.
This commit is contained in:
@@ -2231,6 +2231,11 @@ public:
|
||||
/// attribute list, or \c nullptr if there are none.
|
||||
const DeclAttribute *getEffectiveSendableAttr() const;
|
||||
|
||||
DeclAttribute *getEffectiveSendableAttr() {
|
||||
return const_cast<DeclAttribute *>(
|
||||
const_cast<const DeclAttributes *>(this)->getEffectiveSendableAttr());
|
||||
}
|
||||
|
||||
private:
|
||||
/// Predicate used to filter MatchingAttributeRange.
|
||||
template <typename ATTR, bool AllowInvalid> struct ToAttributeKind {
|
||||
|
||||
@@ -85,6 +85,10 @@ NOTE(unresolvable_clang_decl_is_a_framework_bug,none,
|
||||
WARNING(clang_swift_attr_unhandled,none,
|
||||
"Ignoring unknown Swift attribute or modifier '%0'", (StringRef))
|
||||
|
||||
WARNING(clang_error_code_must_be_sendable,none,
|
||||
"cannot make error code type '%0' non-sendable because Swift errors "
|
||||
"are always sendable", (StringRef))
|
||||
|
||||
WARNING(implicit_bridging_header_imported_from_module,none,
|
||||
"implicit import of bridging header '%0' via module %1 "
|
||||
"is deprecated and will be removed in a later version of Swift",
|
||||
|
||||
@@ -8498,6 +8498,36 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
// The rest of this concerns '@Sendable' and '@_nonSendable`. These don't
|
||||
// affect typealiases, even when there's an underlying nominal type in clang.
|
||||
if (isa<TypeAliasDecl>(MappedDecl))
|
||||
return;
|
||||
|
||||
// Some types have an implicit '@Sendable' attribute.
|
||||
if (ClangDecl->hasAttr<clang::SwiftNewTypeAttr>() ||
|
||||
ClangDecl->hasAttr<clang::EnumExtensibilityAttr>() ||
|
||||
ClangDecl->hasAttr<clang::FlagEnumAttr>() ||
|
||||
ClangDecl->hasAttr<clang::NSErrorDomainAttr>())
|
||||
MappedDecl->getAttrs().add(
|
||||
new (SwiftContext) SendableAttr(/*isImplicit=*/true));
|
||||
|
||||
// 'Error' conforms to 'Sendable', so error wrappers have to be 'Sendable'
|
||||
// and it doesn't make sense for the 'Code' enum to be non-'Sendable'.
|
||||
if (ClangDecl->hasAttr<clang::NSErrorDomainAttr>()) {
|
||||
// If any @_nonSendable attributes are running the show, invalidate and
|
||||
// diagnose them.
|
||||
while (NonSendableAttr *attr = dyn_cast_or_null<NonSendableAttr>(
|
||||
MappedDecl->getAttrs().getEffectiveSendableAttr())) {
|
||||
assert(attr->Specificity == NonSendableKind::Specific &&
|
||||
"didn't we just add an '@Sendable' that should beat this "
|
||||
"'@_nonSendable(_assumed)'?");
|
||||
attr->setInvalid();
|
||||
diagnose(HeaderLoc(ClangDecl->getLocation()),
|
||||
diag::clang_error_code_must_be_sendable,
|
||||
ClangDecl->getNameAsString());
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've collected all @Sendable and @_nonSendable attributes, we
|
||||
// can see if we should synthesize a Sendable conformance.
|
||||
if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
|
||||
|
||||
@@ -124,7 +124,7 @@ class ObjCTest {
|
||||
#endif
|
||||
|
||||
// HEADER: struct TestError : _BridgedStoredNSError {
|
||||
// HEADER: enum Code : Int32, _ErrorCodeProtocol {
|
||||
// HEADER: enum Code : Int32, _ErrorCodeProtocol, @unchecked Sendable {
|
||||
// HEADER: init?(rawValue: Int32)
|
||||
// HEADER: var rawValue: Int32 { get }
|
||||
// HEADER: typealias _ErrorType = TestError
|
||||
@@ -136,7 +136,7 @@ class ObjCTest {
|
||||
// HEADER: func getErr() -> TestError.Code
|
||||
|
||||
// HEADER-NO-PRIVATE: struct TestError : CustomNSError, Hashable, Error {
|
||||
// HEADER-NO-PRIVATE: enum Code : Int32, Equatable {
|
||||
// HEADER-NO-PRIVATE: enum Code : Int32, @unchecked Sendable, Equatable {
|
||||
// HEADER-NO-PRIVATE: init?(rawValue: Int32)
|
||||
// HEADER-NO-PRIVATE: var rawValue: Int32 { get }
|
||||
// HEADER-NO-PRIVATE: typealias _ErrorType = TestError
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules -disable-availability-checking %s -verify -warn-concurrency
|
||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules -disable-availability-checking %s -verify -verify-additional-file %swift_src_root/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h -warn-concurrency
|
||||
|
||||
// REQUIRES: objc_interop
|
||||
// REQUIRES: concurrency
|
||||
@@ -111,15 +111,37 @@ func testSendableInAsync() async {
|
||||
print(x)
|
||||
}
|
||||
|
||||
func testSendableClasses(sendable: SendableClass, nonSendable: NonSendableClass) async {
|
||||
func testSendableAttrs(
|
||||
sendableClass: SendableClass, nonSendableClass: NonSendableClass,
|
||||
sendableEnum: SendableEnum, nonSendableEnum: NonSendableEnum,
|
||||
sendableOptions: SendableOptions, nonSendableOptions: NonSendableOptions,
|
||||
sendableError: SendableError, nonSendableError: NonSendableError,
|
||||
sendableStringEnum: SendableStringEnum, nonSendableStringEnum: NonSendableStringEnum,
|
||||
sendableStringStruct: SendableStringStruct, nonSendableStringStruct: NonSendableStringStruct
|
||||
) async {
|
||||
func takesSendable<T: Sendable>(_: T) {}
|
||||
|
||||
takesSendable(sendable) // no-error
|
||||
takesSendable(nonSendable) // expected-FIXME-warning{{something about missing conformance}}
|
||||
takesSendable(sendableClass) // no-error
|
||||
takesSendable(nonSendableClass) // expected-FIXME-warning{{something about missing conformance}}
|
||||
|
||||
doSomethingConcurrently {
|
||||
print(sendable) // no-error
|
||||
print(nonSendable) // expected-warning{{cannot use parameter 'nonSendable' with a non-sendable type 'NonSendableClass' from concurrently-executed code}}
|
||||
print(sendableClass) // no-error
|
||||
print(nonSendableClass) // expected-warning{{cannot use parameter 'nonSendableClass' with a non-sendable type 'NonSendableClass' from concurrently-executed code}}
|
||||
|
||||
print(sendableEnum) // no-error
|
||||
print(nonSendableEnum) // expected-warning{{cannot use parameter 'nonSendableEnum' with a non-sendable type 'NonSendableEnum' from concurrently-executed code}}
|
||||
|
||||
print(sendableOptions) // no-error
|
||||
print(nonSendableOptions) // expected-warning{{cannot use parameter 'nonSendableOptions' with a non-sendable type 'NonSendableOptions' from concurrently-executed code}}
|
||||
|
||||
print(sendableError) // no-error
|
||||
print(nonSendableError) // no-error--we don't respect `@_nonSendable` on `ns_error_domain` types because all errors are Sendable
|
||||
|
||||
print(sendableStringEnum) // no-error
|
||||
print(nonSendableStringEnum) // expected-warning{{cannot use parameter 'nonSendableStringEnum' with a non-sendable type 'NonSendableStringEnum' from concurrently-executed code}}
|
||||
|
||||
print(sendableStringStruct) // no-error
|
||||
print(nonSendableStringStruct) // expected-warning{{cannot use parameter 'nonSendableStringStruct' with a non-sendable type 'NonSendableStringStruct' from concurrently-executed code}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -I %S/Inputs/custom-modules -I %t
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
// PRINT-LABEL: struct ErrorDomain : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-LABEL: struct ErrorDomain : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: String)
|
||||
// PRINT-NEXT: init(rawValue: String)
|
||||
// PRINT-NEXT: var rawValue: String { get }
|
||||
@@ -26,7 +26,7 @@
|
||||
// PRINT-NEXT: extension Food {
|
||||
// PRINT-NEXT: static let err: ErrorDomain
|
||||
// PRINT-NEXT: }
|
||||
// PRINT-NEXT: struct ClosedEnum : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct ClosedEnum : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(rawValue: String)
|
||||
// PRINT-NEXT: var rawValue: String { get }
|
||||
// PRINT-NEXT: typealias RawValue = String
|
||||
@@ -37,14 +37,14 @@
|
||||
// PRINT-NEXT: static let secondEntry: ClosedEnum
|
||||
// PRINT-NEXT: static let thirdEntry: ClosedEnum
|
||||
// PRINT-NEXT: }
|
||||
// PRINT-NEXT: struct IUONewtype : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct IUONewtype : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: String)
|
||||
// PRINT-NEXT: init(rawValue: String)
|
||||
// PRINT-NEXT: var rawValue: String { get }
|
||||
// PRINT-NEXT: typealias RawValue = String
|
||||
// PRINT-NEXT: typealias _ObjectiveCType = NSString
|
||||
// PRINT-NEXT: }
|
||||
// PRINT-NEXT: struct MyFloat : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct MyFloat : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: Float)
|
||||
// PRINT-NEXT: init(rawValue: Float)
|
||||
// PRINT-NEXT: let rawValue: Float
|
||||
@@ -56,7 +56,7 @@
|
||||
// PRINT-NEXT: static let version: MyFloat{{$}}
|
||||
// PRINT-NEXT: }
|
||||
//
|
||||
// PRINT-LABEL: struct MyInt : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-LABEL: struct MyInt : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: Int32)
|
||||
// PRINT-NEXT: init(rawValue: Int32)
|
||||
// PRINT-NEXT: let rawValue: Int32
|
||||
@@ -83,7 +83,7 @@
|
||||
// PRINT-NEXT: let Notification: String
|
||||
// PRINT-NEXT: let swiftNamedNotification: String
|
||||
//
|
||||
// PRINT-LABEL: struct CFNewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-LABEL: struct CFNewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: CFString)
|
||||
// PRINT-NEXT: init(rawValue: CFString)
|
||||
// PRINT-NEXT: let rawValue: CFString
|
||||
@@ -97,7 +97,7 @@
|
||||
// PRINT-NEXT: func FooAudited() -> CFNewType
|
||||
// PRINT-NEXT: func FooUnaudited() -> Unmanaged<CFString>
|
||||
//
|
||||
// PRINT-LABEL: struct MyABINewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-LABEL: struct MyABINewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: CFString)
|
||||
// PRINT-NEXT: init(rawValue: CFString)
|
||||
// PRINT-NEXT: let rawValue: CFString
|
||||
@@ -114,7 +114,7 @@
|
||||
// PRINT-NEXT: func takeMyABIOldType(_: MyABIOldType!)
|
||||
// PRINT-NEXT: func takeMyABINewTypeNonNull(_: MyABINewType)
|
||||
// PRINT-NEXT: func takeMyABIOldTypeNonNull(_: MyABIOldType)
|
||||
// PRINT-LABEL: struct MyABINewTypeNS : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-LABEL: struct MyABINewTypeNS : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: String)
|
||||
// PRINT-NEXT: init(rawValue: String)
|
||||
// PRINT-NEXT: var rawValue: String { get }
|
||||
@@ -133,7 +133,7 @@
|
||||
// PRINT-NEXT: var i: Int32
|
||||
// PRINT-NEXT: }
|
||||
// PRINT-NEXT: extension NSSomeContext {
|
||||
// PRINT-NEXT: struct Name : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct Name : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: String)
|
||||
// PRINT-NEXT: init(rawValue: String)
|
||||
// PRINT-NEXT: var rawValue: String { get }
|
||||
@@ -145,13 +145,13 @@
|
||||
// PRINT-NEXT: static let myContextName: NSSomeContext.Name
|
||||
// PRINT-NEXT: }
|
||||
//
|
||||
// PRINT-NEXT: struct TRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct TRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: OpaquePointer)
|
||||
// PRINT-NEXT: init(rawValue: OpaquePointer)
|
||||
// PRINT-NEXT: let rawValue: OpaquePointer
|
||||
// PRINT-NEXT: typealias RawValue = OpaquePointer
|
||||
// PRINT-NEXT: }
|
||||
// PRINT-NEXT: struct ConstTRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct ConstTRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: OpaquePointer)
|
||||
// PRINT-NEXT: init(rawValue: OpaquePointer)
|
||||
// PRINT-NEXT: let rawValue: OpaquePointer
|
||||
@@ -169,13 +169,13 @@
|
||||
// PRINT-NEXT: func use()
|
||||
// PRINT-NEXT: }
|
||||
//
|
||||
// PRINT-NEXT: struct TRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct TRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: UnsafeMutablePointer<OpaquePointer>)
|
||||
// PRINT-NEXT: init(rawValue: UnsafeMutablePointer<OpaquePointer>)
|
||||
// PRINT-NEXT: let rawValue: UnsafeMutablePointer<OpaquePointer>
|
||||
// PRINT-NEXT: typealias RawValue = UnsafeMutablePointer<OpaquePointer>
|
||||
// PRINT-NEXT: }
|
||||
// PRINT-NEXT: struct ConstTRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
|
||||
// PRINT-NEXT: struct ConstTRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
|
||||
// PRINT-NEXT: init(_ rawValue: UnsafePointer<OpaquePointer>)
|
||||
// PRINT-NEXT: init(rawValue: UnsafePointer<OpaquePointer>)
|
||||
// PRINT-NEXT: let rawValue: UnsafePointer<OpaquePointer>
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
// CHECK: enum Normal : Int {
|
||||
// CHECK-LABEL: enum Normal : Int, @unchecked Sendable {
|
||||
// CHECK-NOT: {{^}}}
|
||||
// CHECK: case one
|
||||
// CHECK-NEXT: case two
|
||||
// CHECK-NEXT: case three
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: enum SwiftEnum : Int {
|
||||
// CHECK-LABEL: enum SwiftEnum : Int, @unchecked Sendable {
|
||||
// CHECK-NOT: {{^}}}
|
||||
// CHECK: case one
|
||||
// CHECK-NEXT: case two
|
||||
// CHECK-NEXT: case three
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// CHECK: enum SwiftEnumTwo : Int {
|
||||
// CHECK-LABEL: enum SwiftEnumTwo : Int, @unchecked Sendable {
|
||||
// CHECK-NOT: {{^}}}
|
||||
// CHECK: case SwiftEnumTwoA
|
||||
// CHECK-NEXT: case SwiftEnumTwoB
|
||||
|
||||
@@ -23,6 +23,7 @@ import _Concurrency
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: class NonSendableClass
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension NonSendableClass : @unchecked Sendable {
|
||||
|
||||
@@ -30,10 +31,54 @@ import _Concurrency
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: class AuditedNonSendable
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension AuditedNonSendable : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: class AuditedBoth
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension AuditedBoth : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: enum SendableEnum :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: enum NonSendableEnum :
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension NonSendableEnum : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: struct SendableOptions :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: struct NonSendableOptions :
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension NonSendableOptions : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: public struct SendableError :
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: public enum Code :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: public struct NonSendableError :
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: public enum Code :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: struct SendableStringEnum :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: struct NonSendableStringEnum :
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension NonSendableStringEnum : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: struct SendableStringStruct :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: struct NonSendableStringStruct :
|
||||
// CHECK-NOT: @unchecked Sendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension NonSendableStringStruct : @unchecked Sendable {
|
||||
|
||||
|
||||
@@ -19,8 +19,15 @@
|
||||
#define ASSUME_NONSENDABLE_END
|
||||
#endif
|
||||
|
||||
#define NS_ENUM(_type, _name) enum _name : _type _name; \
|
||||
enum __attribute__((enum_extensibility(open))) _name : _type
|
||||
#define NS_OPTIONS(_type, _name) enum _name : _type _name; \
|
||||
enum __attribute__((enum_extensibility(open), flag_enum)) _name : _type
|
||||
#define NS_ERROR_ENUM(_type, _name, _domain) \
|
||||
enum _name : _type _name; enum __attribute__((ns_error_domain(_domain))) _name : _type
|
||||
#define NS_STRING_ENUM __attribute((swift_newtype(enum)))
|
||||
#define NS_EXTENSIBLE_STRING_ENUM __attribute__((swift_wrapper(struct)))
|
||||
|
||||
#define NS_EXTENSIBLE_STRING_ENUM __attribute__((swift_wrapper(struct)));
|
||||
typedef NSString *Flavor NS_EXTENSIBLE_STRING_ENUM;
|
||||
|
||||
@protocol ServiceProvider
|
||||
@@ -210,6 +217,35 @@ SENDABLE @interface AuditedSendable : NSObject @end
|
||||
@interface AuditedNonSendable : NSObject @end
|
||||
NONSENDABLE SENDABLE @interface AuditedBoth : NSObject @end
|
||||
|
||||
typedef NS_ENUM(unsigned, SendableEnum) {
|
||||
SendableEnumFoo, SendableEnumBar
|
||||
};
|
||||
typedef NS_ENUM(unsigned, NonSendableEnum) {
|
||||
NonSendableEnumFoo, NonSendableEnumBar
|
||||
} NONSENDABLE;
|
||||
|
||||
typedef NS_OPTIONS(unsigned, SendableOptions) {
|
||||
SendableOptionsFoo = 1 << 0, SendableOptionsBar = 1 << 1
|
||||
};
|
||||
typedef NS_OPTIONS(unsigned, NonSendableOptions) {
|
||||
NonSendableOptionsFoo = 1 << 0, NonSendableOptionsBar = 1 << 1
|
||||
} NONSENDABLE;
|
||||
|
||||
NSString *SendableErrorDomain, *NonSendableErrorDomain;
|
||||
typedef NS_ERROR_ENUM(unsigned, SendableErrorCode, SendableErrorDomain) {
|
||||
SendableErrorCodeFoo, SendableErrorCodeBar
|
||||
};
|
||||
typedef NS_ERROR_ENUM(unsigned, NonSendableErrorCode, NonSendableErrorDomain) {
|
||||
NonSendableErrorCodeFoo, NonSendableErrorCodeBar
|
||||
} NONSENDABLE;
|
||||
// expected-warning@-3 {{cannot make error code type 'NonSendableErrorCode' non-sendable because Swift errors are always sendable}}
|
||||
|
||||
typedef NSString *SendableStringEnum NS_STRING_ENUM;
|
||||
typedef NSString *NonSendableStringEnum NS_STRING_ENUM NONSENDABLE;
|
||||
|
||||
typedef NSString *SendableStringStruct NS_EXTENSIBLE_STRING_ENUM;
|
||||
typedef NSString *NonSendableStringStruct NS_EXTENSIBLE_STRING_ENUM NONSENDABLE;
|
||||
|
||||
ASSUME_NONSENDABLE_END
|
||||
|
||||
#pragma clang assume_nonnull end
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// CHECK-NEXT: var rawValue: [[ENUM_UNDERLYING_TYPE]]
|
||||
// CHECK-NEXT: typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: @frozen enum PublicClosedEnum : [[ENUM_UNDERLYING_TYPE]] {
|
||||
// CHECK-NEXT: @frozen enum PublicClosedEnum : [[ENUM_UNDERLYING_TYPE]], @unchecked Sendable {
|
||||
// CHECK-NEXT: init?(rawValue: [[ENUM_UNDERLYING_TYPE]])
|
||||
// CHECK-NEXT: var rawValue: [[ENUM_UNDERLYING_TYPE]] { get }
|
||||
// CHECK-NEXT: typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
|
||||
@@ -25,7 +25,7 @@
|
||||
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "value1")
|
||||
// CHECK-NEXT: static var Value1: PublicPrivate.PublicClosedEnum { get }
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: enum PublicOpenEnum : [[ENUM_UNDERLYING_TYPE]] {
|
||||
// CHECK-NEXT: enum PublicOpenEnum : [[ENUM_UNDERLYING_TYPE]], @unchecked Sendable {
|
||||
// CHECK-NEXT: init?(rawValue: [[ENUM_UNDERLYING_TYPE]])
|
||||
// CHECK-NEXT: var rawValue: [[ENUM_UNDERLYING_TYPE]] { get }
|
||||
// CHECK-NEXT: typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
|
||||
@@ -33,7 +33,7 @@
|
||||
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "value1")
|
||||
// CHECK-NEXT: static var Value1: PublicPrivate.PublicOpenEnum { get }
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: struct PublicFlagEnum : OptionSet {
|
||||
// CHECK-NEXT: struct PublicFlagEnum : OptionSet, @unchecked Sendable {
|
||||
// CHECK-NEXT: init(rawValue: [[ENUM_UNDERLYING_TYPE]])
|
||||
// CHECK-NEXT: let rawValue: [[ENUM_UNDERLYING_TYPE]]
|
||||
// CHECK-NEXT: typealias RawValue = [[ENUM_UNDERLYING_TYPE]]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// RUN: %FileCheck -input-file=%t.response %s
|
||||
|
||||
// CHECK: struct MyError : CustomNSError, Hashable, Error {
|
||||
// CHECK: enum Code : Int32, Equatable {
|
||||
// CHECK: enum Code : Int32, @unchecked Sendable, Equatable {
|
||||
// CHECK: case errFirst
|
||||
// CHECK: case errSecond
|
||||
// CHECK: }
|
||||
|
||||
Reference in New Issue
Block a user