Skip to content

Commit ad0e709

Browse files
committed
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.
1 parent 8007d70 commit ad0e709

File tree

11 files changed

+171
-29
lines changed

11 files changed

+171
-29
lines changed

include/swift/AST/Attr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,6 +2231,11 @@ class DeclAttributes {
22312231
/// attribute list, or \c nullptr if there are none.
22322232
const DeclAttribute *getEffectiveSendableAttr() const;
22332233

2234+
DeclAttribute *getEffectiveSendableAttr() {
2235+
return const_cast<DeclAttribute *>(
2236+
const_cast<const DeclAttributes *>(this)->getEffectiveSendableAttr());
2237+
}
2238+
22342239
private:
22352240
/// Predicate used to filter MatchingAttributeRange.
22362241
template <typename ATTR, bool AllowInvalid> struct ToAttributeKind {

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ NOTE(unresolvable_clang_decl_is_a_framework_bug,none,
8585
WARNING(clang_swift_attr_unhandled,none,
8686
"Ignoring unknown Swift attribute or modifier '%0'", (StringRef))
8787

88+
WARNING(clang_error_code_must_be_sendable,none,
89+
"cannot make error code type '%0' non-sendable because Swift errors "
90+
"are always sendable", (StringRef))
91+
8892
WARNING(implicit_bridging_header_imported_from_module,none,
8993
"implicit import of bridging header '%0' via module %1 "
9094
"is deprecated and will be removed in a later version of Swift",

lib/ClangImporter/ImportDecl.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8498,6 +8498,36 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84988498
}
84998499
}
85008500

8501+
// The rest of this concerns '@Sendable' and '@_nonSendable`. These don't
8502+
// affect typealiases, even when there's an underlying nominal type in clang.
8503+
if (isa<TypeAliasDecl>(MappedDecl))
8504+
return;
8505+
8506+
// Some types have an implicit '@Sendable' attribute.
8507+
if (ClangDecl->hasAttr<clang::SwiftNewTypeAttr>() ||
8508+
ClangDecl->hasAttr<clang::EnumExtensibilityAttr>() ||
8509+
ClangDecl->hasAttr<clang::FlagEnumAttr>() ||
8510+
ClangDecl->hasAttr<clang::NSErrorDomainAttr>())
8511+
MappedDecl->getAttrs().add(
8512+
new (SwiftContext) SendableAttr(/*isImplicit=*/true));
8513+
8514+
// 'Error' conforms to 'Sendable', so error wrappers have to be 'Sendable'
8515+
// and it doesn't make sense for the 'Code' enum to be non-'Sendable'.
8516+
if (ClangDecl->hasAttr<clang::NSErrorDomainAttr>()) {
8517+
// If any @_nonSendable attributes are running the show, invalidate and
8518+
// diagnose them.
8519+
while (NonSendableAttr *attr = dyn_cast_or_null<NonSendableAttr>(
8520+
MappedDecl->getAttrs().getEffectiveSendableAttr())) {
8521+
assert(attr->Specificity == NonSendableKind::Specific &&
8522+
"didn't we just add an '@Sendable' that should beat this "
8523+
"'@_nonSendable(_assumed)'?");
8524+
attr->setInvalid();
8525+
diagnose(HeaderLoc(ClangDecl->getLocation()),
8526+
diag::clang_error_code_must_be_sendable,
8527+
ClangDecl->getNameAsString());
8528+
}
8529+
}
8530+
85018531
// Now that we've collected all @Sendable and @_nonSendable attributes, we
85028532
// can see if we should synthesize a Sendable conformance.
85038533
if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {

test/ClangImporter/enum-error.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class ObjCTest {
124124
#endif
125125

126126
// HEADER: struct TestError : _BridgedStoredNSError {
127-
// HEADER: enum Code : Int32, _ErrorCodeProtocol {
127+
// HEADER: enum Code : Int32, _ErrorCodeProtocol, @unchecked Sendable {
128128
// HEADER: init?(rawValue: Int32)
129129
// HEADER: var rawValue: Int32 { get }
130130
// HEADER: typealias _ErrorType = TestError
@@ -136,7 +136,7 @@ class ObjCTest {
136136
// HEADER: func getErr() -> TestError.Code
137137

138138
// HEADER-NO-PRIVATE: struct TestError : CustomNSError, Hashable, Error {
139-
// HEADER-NO-PRIVATE: enum Code : Int32, Equatable {
139+
// HEADER-NO-PRIVATE: enum Code : Int32, @unchecked Sendable, Equatable {
140140
// HEADER-NO-PRIVATE: init?(rawValue: Int32)
141141
// HEADER-NO-PRIVATE: var rawValue: Int32 { get }
142142
// HEADER-NO-PRIVATE: typealias _ErrorType = TestError

test/ClangImporter/objc_async.swift

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules -disable-availability-checking %s -verify -warn-concurrency
1+
// 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
22

33
// REQUIRES: objc_interop
44
// REQUIRES: concurrency
@@ -111,15 +111,37 @@ func testSendableInAsync() async {
111111
print(x)
112112
}
113113

114-
func testSendableClasses(sendable: SendableClass, nonSendable: NonSendableClass) async {
114+
func testSendableAttrs(
115+
sendableClass: SendableClass, nonSendableClass: NonSendableClass,
116+
sendableEnum: SendableEnum, nonSendableEnum: NonSendableEnum,
117+
sendableOptions: SendableOptions, nonSendableOptions: NonSendableOptions,
118+
sendableError: SendableError, nonSendableError: NonSendableError,
119+
sendableStringEnum: SendableStringEnum, nonSendableStringEnum: NonSendableStringEnum,
120+
sendableStringStruct: SendableStringStruct, nonSendableStringStruct: NonSendableStringStruct
121+
) async {
115122
func takesSendable<T: Sendable>(_: T) {}
116123

117-
takesSendable(sendable) // no-error
118-
takesSendable(nonSendable) // expected-FIXME-warning{{something about missing conformance}}
124+
takesSendable(sendableClass) // no-error
125+
takesSendable(nonSendableClass) // expected-FIXME-warning{{something about missing conformance}}
119126

120127
doSomethingConcurrently {
121-
print(sendable) // no-error
122-
print(nonSendable) // expected-warning{{cannot use parameter 'nonSendable' with a non-sendable type 'NonSendableClass' from concurrently-executed code}}
128+
print(sendableClass) // no-error
129+
print(nonSendableClass) // expected-warning{{cannot use parameter 'nonSendableClass' with a non-sendable type 'NonSendableClass' from concurrently-executed code}}
130+
131+
print(sendableEnum) // no-error
132+
print(nonSendableEnum) // expected-warning{{cannot use parameter 'nonSendableEnum' with a non-sendable type 'NonSendableEnum' from concurrently-executed code}}
133+
134+
print(sendableOptions) // no-error
135+
print(nonSendableOptions) // expected-warning{{cannot use parameter 'nonSendableOptions' with a non-sendable type 'NonSendableOptions' from concurrently-executed code}}
136+
137+
print(sendableError) // no-error
138+
print(nonSendableError) // no-error--we don't respect `@_nonSendable` on `ns_error_domain` types because all errors are Sendable
139+
140+
print(sendableStringEnum) // no-error
141+
print(nonSendableStringEnum) // expected-warning{{cannot use parameter 'nonSendableStringEnum' with a non-sendable type 'NonSendableStringEnum' from concurrently-executed code}}
142+
143+
print(sendableStringStruct) // no-error
144+
print(nonSendableStringStruct) // expected-warning{{cannot use parameter 'nonSendableStringStruct' with a non-sendable type 'NonSendableStringStruct' from concurrently-executed code}}
123145
}
124146
}
125147

test/IDE/newtype.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -I %S/Inputs/custom-modules -I %t
66
// REQUIRES: objc_interop
77

8-
// PRINT-LABEL: struct ErrorDomain : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
8+
// PRINT-LABEL: struct ErrorDomain : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
99
// PRINT-NEXT: init(_ rawValue: String)
1010
// PRINT-NEXT: init(rawValue: String)
1111
// PRINT-NEXT: var rawValue: String { get }
@@ -26,7 +26,7 @@
2626
// PRINT-NEXT: extension Food {
2727
// PRINT-NEXT: static let err: ErrorDomain
2828
// PRINT-NEXT: }
29-
// PRINT-NEXT: struct ClosedEnum : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
29+
// PRINT-NEXT: struct ClosedEnum : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
3030
// PRINT-NEXT: init(rawValue: String)
3131
// PRINT-NEXT: var rawValue: String { get }
3232
// PRINT-NEXT: typealias RawValue = String
@@ -37,14 +37,14 @@
3737
// PRINT-NEXT: static let secondEntry: ClosedEnum
3838
// PRINT-NEXT: static let thirdEntry: ClosedEnum
3939
// PRINT-NEXT: }
40-
// PRINT-NEXT: struct IUONewtype : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
40+
// PRINT-NEXT: struct IUONewtype : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
4141
// PRINT-NEXT: init(_ rawValue: String)
4242
// PRINT-NEXT: init(rawValue: String)
4343
// PRINT-NEXT: var rawValue: String { get }
4444
// PRINT-NEXT: typealias RawValue = String
4545
// PRINT-NEXT: typealias _ObjectiveCType = NSString
4646
// PRINT-NEXT: }
47-
// PRINT-NEXT: struct MyFloat : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
47+
// PRINT-NEXT: struct MyFloat : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
4848
// PRINT-NEXT: init(_ rawValue: Float)
4949
// PRINT-NEXT: init(rawValue: Float)
5050
// PRINT-NEXT: let rawValue: Float
@@ -56,7 +56,7 @@
5656
// PRINT-NEXT: static let version: MyFloat{{$}}
5757
// PRINT-NEXT: }
5858
//
59-
// PRINT-LABEL: struct MyInt : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
59+
// PRINT-LABEL: struct MyInt : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
6060
// PRINT-NEXT: init(_ rawValue: Int32)
6161
// PRINT-NEXT: init(rawValue: Int32)
6262
// PRINT-NEXT: let rawValue: Int32
@@ -83,7 +83,7 @@
8383
// PRINT-NEXT: let Notification: String
8484
// PRINT-NEXT: let swiftNamedNotification: String
8585
//
86-
// PRINT-LABEL: struct CFNewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
86+
// PRINT-LABEL: struct CFNewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
8787
// PRINT-NEXT: init(_ rawValue: CFString)
8888
// PRINT-NEXT: init(rawValue: CFString)
8989
// PRINT-NEXT: let rawValue: CFString
@@ -97,7 +97,7 @@
9797
// PRINT-NEXT: func FooAudited() -> CFNewType
9898
// PRINT-NEXT: func FooUnaudited() -> Unmanaged<CFString>
9999
//
100-
// PRINT-LABEL: struct MyABINewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
100+
// PRINT-LABEL: struct MyABINewType : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
101101
// PRINT-NEXT: init(_ rawValue: CFString)
102102
// PRINT-NEXT: init(rawValue: CFString)
103103
// PRINT-NEXT: let rawValue: CFString
@@ -114,7 +114,7 @@
114114
// PRINT-NEXT: func takeMyABIOldType(_: MyABIOldType!)
115115
// PRINT-NEXT: func takeMyABINewTypeNonNull(_: MyABINewType)
116116
// PRINT-NEXT: func takeMyABIOldTypeNonNull(_: MyABIOldType)
117-
// PRINT-LABEL: struct MyABINewTypeNS : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
117+
// PRINT-LABEL: struct MyABINewTypeNS : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
118118
// PRINT-NEXT: init(_ rawValue: String)
119119
// PRINT-NEXT: init(rawValue: String)
120120
// PRINT-NEXT: var rawValue: String { get }
@@ -133,7 +133,7 @@
133133
// PRINT-NEXT: var i: Int32
134134
// PRINT-NEXT: }
135135
// PRINT-NEXT: extension NSSomeContext {
136-
// PRINT-NEXT: struct Name : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
136+
// PRINT-NEXT: struct Name : _ObjectiveCBridgeable, Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
137137
// PRINT-NEXT: init(_ rawValue: String)
138138
// PRINT-NEXT: init(rawValue: String)
139139
// PRINT-NEXT: var rawValue: String { get }
@@ -145,13 +145,13 @@
145145
// PRINT-NEXT: static let myContextName: NSSomeContext.Name
146146
// PRINT-NEXT: }
147147
//
148-
// PRINT-NEXT: struct TRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
148+
// PRINT-NEXT: struct TRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
149149
// PRINT-NEXT: init(_ rawValue: OpaquePointer)
150150
// PRINT-NEXT: init(rawValue: OpaquePointer)
151151
// PRINT-NEXT: let rawValue: OpaquePointer
152152
// PRINT-NEXT: typealias RawValue = OpaquePointer
153153
// PRINT-NEXT: }
154-
// PRINT-NEXT: struct ConstTRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
154+
// PRINT-NEXT: struct ConstTRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
155155
// PRINT-NEXT: init(_ rawValue: OpaquePointer)
156156
// PRINT-NEXT: init(rawValue: OpaquePointer)
157157
// PRINT-NEXT: let rawValue: OpaquePointer
@@ -169,13 +169,13 @@
169169
// PRINT-NEXT: func use()
170170
// PRINT-NEXT: }
171171
//
172-
// PRINT-NEXT: struct TRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
172+
// PRINT-NEXT: struct TRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
173173
// PRINT-NEXT: init(_ rawValue: UnsafeMutablePointer<OpaquePointer>)
174174
// PRINT-NEXT: init(rawValue: UnsafeMutablePointer<OpaquePointer>)
175175
// PRINT-NEXT: let rawValue: UnsafeMutablePointer<OpaquePointer>
176176
// PRINT-NEXT: typealias RawValue = UnsafeMutablePointer<OpaquePointer>
177177
// PRINT-NEXT: }
178-
// PRINT-NEXT: struct ConstTRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable {
178+
// PRINT-NEXT: struct ConstTRefRef : Hashable, Equatable, _SwiftNewtypeWrapper, RawRepresentable, @unchecked Sendable {
179179
// PRINT-NEXT: init(_ rawValue: UnsafePointer<OpaquePointer>)
180180
// PRINT-NEXT: init(rawValue: UnsafePointer<OpaquePointer>)
181181
// PRINT-NEXT: let rawValue: UnsafePointer<OpaquePointer>

test/IDE/print_clang_header_swift_name.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55

66
// REQUIRES: objc_interop
77

8-
// CHECK: enum Normal : Int {
8+
// CHECK-LABEL: enum Normal : Int, @unchecked Sendable {
99
// CHECK-NOT: {{^}}}
1010
// CHECK: case one
1111
// CHECK-NEXT: case two
1212
// CHECK-NEXT: case three
1313
// CHECK-NEXT: }
1414

15-
// CHECK: enum SwiftEnum : Int {
15+
// CHECK-LABEL: enum SwiftEnum : Int, @unchecked Sendable {
1616
// CHECK-NOT: {{^}}}
1717
// CHECK: case one
1818
// CHECK-NEXT: case two
1919
// CHECK-NEXT: case three
2020
// CHECK-NEXT: }
2121

22-
// CHECK: enum SwiftEnumTwo : Int {
22+
// CHECK-LABEL: enum SwiftEnumTwo : Int, @unchecked Sendable {
2323
// CHECK-NOT: {{^}}}
2424
// CHECK: case SwiftEnumTwoA
2525
// CHECK-NEXT: case SwiftEnumTwoB

test/IDE/print_objc_concurrency_interface.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,62 @@ import _Concurrency
2323
// CHECK-SAME: @unchecked Sendable
2424

2525
// CHECK-LABEL: class NonSendableClass
26+
// CHECK-NOT: @unchecked Sendable
2627
// CHECK: @available(*, unavailable)
2728
// CHECK-NEXT: extension NonSendableClass : @unchecked Sendable {
2829

2930
// CHECK-LABEL: class AuditedSendable :
3031
// CHECK-SAME: @unchecked Sendable
3132

3233
// CHECK-LABEL: class AuditedNonSendable
34+
// CHECK-NOT: @unchecked Sendable
3335
// CHECK: @available(*, unavailable)
3436
// CHECK-NEXT: extension AuditedNonSendable : @unchecked Sendable {
3537

3638
// CHECK-LABEL: class AuditedBoth
39+
// CHECK-NOT: @unchecked Sendable
3740
// CHECK: @available(*, unavailable)
3841
// CHECK-NEXT: extension AuditedBoth : @unchecked Sendable {
3942

43+
// CHECK-LABEL: enum SendableEnum :
44+
// CHECK-SAME: @unchecked Sendable
45+
46+
// CHECK-LABEL: enum NonSendableEnum :
47+
// CHECK-NOT: @unchecked Sendable
48+
// CHECK: @available(*, unavailable)
49+
// CHECK-NEXT: extension NonSendableEnum : @unchecked Sendable {
50+
51+
// CHECK-LABEL: struct SendableOptions :
52+
// CHECK-SAME: @unchecked Sendable
53+
54+
// CHECK-LABEL: struct NonSendableOptions :
55+
// CHECK-NOT: @unchecked Sendable
56+
// CHECK: @available(*, unavailable)
57+
// CHECK-NEXT: extension NonSendableOptions : @unchecked Sendable {
58+
59+
// CHECK-LABEL: public struct SendableError :
60+
// CHECK-NOT: @unchecked Sendable
61+
// CHECK: public enum Code :
62+
// CHECK-SAME: @unchecked Sendable
63+
64+
// CHECK-LABEL: public struct NonSendableError :
65+
// CHECK-NOT: @unchecked Sendable
66+
// CHECK: public enum Code :
67+
// CHECK-SAME: @unchecked Sendable
68+
69+
// CHECK-LABEL: struct SendableStringEnum :
70+
// CHECK-SAME: @unchecked Sendable
71+
72+
// CHECK-LABEL: struct NonSendableStringEnum :
73+
// CHECK-NOT: @unchecked Sendable
74+
// CHECK: @available(*, unavailable)
75+
// CHECK-NEXT: extension NonSendableStringEnum : @unchecked Sendable {
76+
77+
// CHECK-LABEL: struct SendableStringStruct :
78+
// CHECK-SAME: @unchecked Sendable
79+
80+
// CHECK-LABEL: struct NonSendableStringStruct :
81+
// CHECK-NOT: @unchecked Sendable
82+
// CHECK: @available(*, unavailable)
83+
// CHECK-NEXT: extension NonSendableStringStruct : @unchecked Sendable {
84+

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,15 @@
1919
#define ASSUME_NONSENDABLE_END
2020
#endif
2121

22+
#define NS_ENUM(_type, _name) enum _name : _type _name; \
23+
enum __attribute__((enum_extensibility(open))) _name : _type
24+
#define NS_OPTIONS(_type, _name) enum _name : _type _name; \
25+
enum __attribute__((enum_extensibility(open), flag_enum)) _name : _type
26+
#define NS_ERROR_ENUM(_type, _name, _domain) \
27+
enum _name : _type _name; enum __attribute__((ns_error_domain(_domain))) _name : _type
28+
#define NS_STRING_ENUM __attribute((swift_newtype(enum)))
29+
#define NS_EXTENSIBLE_STRING_ENUM __attribute__((swift_wrapper(struct)))
2230

23-
#define NS_EXTENSIBLE_STRING_ENUM __attribute__((swift_wrapper(struct)));
2431
typedef NSString *Flavor NS_EXTENSIBLE_STRING_ENUM;
2532

2633
@protocol ServiceProvider
@@ -210,6 +217,35 @@ SENDABLE @interface AuditedSendable : NSObject @end
210217
@interface AuditedNonSendable : NSObject @end
211218
NONSENDABLE SENDABLE @interface AuditedBoth : NSObject @end
212219

220+
typedef NS_ENUM(unsigned, SendableEnum) {
221+
SendableEnumFoo, SendableEnumBar
222+
};
223+
typedef NS_ENUM(unsigned, NonSendableEnum) {
224+
NonSendableEnumFoo, NonSendableEnumBar
225+
} NONSENDABLE;
226+
227+
typedef NS_OPTIONS(unsigned, SendableOptions) {
228+
SendableOptionsFoo = 1 << 0, SendableOptionsBar = 1 << 1
229+
};
230+
typedef NS_OPTIONS(unsigned, NonSendableOptions) {
231+
NonSendableOptionsFoo = 1 << 0, NonSendableOptionsBar = 1 << 1
232+
} NONSENDABLE;
233+
234+
NSString *SendableErrorDomain, *NonSendableErrorDomain;
235+
typedef NS_ERROR_ENUM(unsigned, SendableErrorCode, SendableErrorDomain) {
236+
SendableErrorCodeFoo, SendableErrorCodeBar
237+
};
238+
typedef NS_ERROR_ENUM(unsigned, NonSendableErrorCode, NonSendableErrorDomain) {
239+
NonSendableErrorCodeFoo, NonSendableErrorCodeBar
240+
} NONSENDABLE;
241+
// expected-warning@-3 {{cannot make error code type 'NonSendableErrorCode' non-sendable because Swift errors are always sendable}}
242+
243+
typedef NSString *SendableStringEnum NS_STRING_ENUM;
244+
typedef NSString *NonSendableStringEnum NS_STRING_ENUM NONSENDABLE;
245+
246+
typedef NSString *SendableStringStruct NS_EXTENSIBLE_STRING_ENUM;
247+
typedef NSString *NonSendableStringStruct NS_EXTENSIBLE_STRING_ENUM NONSENDABLE;
248+
213249
ASSUME_NONSENDABLE_END
214250

215251
#pragma clang assume_nonnull end

0 commit comments

Comments
 (0)