|
| 1 | +// RUN: %empty-directory(%t/src) |
| 2 | +// RUN: %empty-directory(%t/sdk) |
| 3 | +// RUN: split-file %s %t/src |
| 4 | + |
| 5 | +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %t/src/main.swift \ |
| 6 | +// RUN: -import-objc-header %t/src/Test.h \ |
| 7 | +// RUN: -strict-concurrency=complete \ |
| 8 | +// RUN: -module-name main -I %t -verify |
| 9 | + |
| 10 | +// REQUIRES: objc_interop |
| 11 | +// REQUIRES: concurrency |
| 12 | + |
| 13 | +//--- Test.h |
| 14 | +#define NS_SWIFT_SENDABLE __attribute__((__swift_attr__("@Sendable"))) |
| 15 | + |
| 16 | +#pragma clang assume_nonnull begin |
| 17 | + |
| 18 | +@import Foundation; |
| 19 | + |
| 20 | +NS_SWIFT_SENDABLE |
| 21 | +@protocol MyObjCProtocol <NSObject> |
| 22 | +@property (readonly, nonatomic) NSString *test; |
| 23 | +@end |
| 24 | + |
| 25 | +@protocol MyRefinedObjCProtocol <MyObjCProtocol> |
| 26 | +@end |
| 27 | + |
| 28 | +#pragma clang assume_nonnull end |
| 29 | + |
| 30 | +//--- main.swift |
| 31 | +struct MyStruct: Sendable { |
| 32 | + let value: any MyObjCProtocol // Ok |
| 33 | +} |
| 34 | + |
| 35 | +extension Sendable { |
| 36 | + func compute() {} |
| 37 | +} |
| 38 | + |
| 39 | +extension MyObjCProtocol { |
| 40 | + func test() { |
| 41 | + compute() // Ok |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +class K : NSObject, MyObjCProtocol { |
| 46 | + // expected-warning@-1 {{non-final class 'K' cannot conform to 'Sendable'; use '@unchecked Sendable'}} |
| 47 | + let test: String = "k" |
| 48 | +} |
| 49 | + |
| 50 | +class UncheckedK : NSObject, MyObjCProtocol, @unchecked Sendable { // ok |
| 51 | + let test: String = "unchecked" |
| 52 | +} |
| 53 | + |
| 54 | +class KRefined : NSObject, MyRefinedObjCProtocol { |
| 55 | + // expected-warning@-1 {{non-final class 'KRefined' cannot conform to 'Sendable'; use '@unchecked Sendable'}} |
| 56 | + let test: String = "refined" |
| 57 | +} |
| 58 | + |
| 59 | +class KUncheckedRefined : NSObject, MyRefinedObjCProtocol, @unchecked Sendable { // Ok |
| 60 | + let test: String = "refined unchecked" |
| 61 | +} |
| 62 | + |
| 63 | +@preconcurrency |
| 64 | +protocol P : Sendable { |
| 65 | +} |
| 66 | + |
| 67 | +protocol Q : Sendable { |
| 68 | +} |
| 69 | + |
| 70 | +do { |
| 71 | + class A : NSObject {} |
| 72 | + |
| 73 | + final class B : A, P { |
| 74 | + // expected-warning@-1 {{'Sendable' class 'B' cannot inherit from another class other than 'NSObject'}} |
| 75 | + } |
| 76 | + |
| 77 | + final class UncheckedB : A, P, @unchecked Sendable { // Ok |
| 78 | + } |
| 79 | + |
| 80 | + class C : A, MyObjCProtocol { |
| 81 | + // expected-warning@-1 {{non-final class 'C' cannot conform to 'Sendable'; use '@unchecked Sendable'}} |
| 82 | + // expected-warning@-2 {{'Sendable' class 'C' cannot inherit from another class other than 'NSObject'}} |
| 83 | + let test: String = "c" |
| 84 | + } |
| 85 | + |
| 86 | + class UncheckedC : A, MyObjCProtocol, @unchecked Sendable { // Ok |
| 87 | + let test: String = "c" |
| 88 | + } |
| 89 | + |
| 90 | + // A warning until `-swift-version 6` |
| 91 | + final class D : A, Q { |
| 92 | + // expected-warning@-1 {{'Sendable' class 'D' cannot inherit from another class other than 'NSObject'}} |
| 93 | + } |
| 94 | + |
| 95 | + final class UncheckedD : A, Q, @unchecked Sendable { // Ok |
| 96 | + } |
| 97 | +} |
| 98 | + |
| 99 | +do { |
| 100 | + func testSendable<T: Sendable>(_: T) {} |
| 101 | + |
| 102 | + testSendable(K()) // Ok |
| 103 | + testSendable(UncheckedK()) // Ok |
| 104 | + testSendable(KRefined()) // Ok |
| 105 | + testSendable(KUncheckedRefined()) // Ok |
| 106 | +} |
0 commit comments