mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
259 lines
8.8 KiB
Swift
259 lines
8.8 KiB
Swift
// RUN: %target-typecheck-verify-swift -strict-concurrency=targeted
|
|
// REQUIRES: concurrency
|
|
// REQUIRES: OS=macosx
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
struct NS1 { }
|
|
// expected-note@-1 2{{consider making struct 'NS1' conform to the 'Sendable' protocol}}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
@available(*, unavailable)
|
|
extension NS1: Sendable { }
|
|
// expected-note@-1 4{{conformance of 'NS1' to 'Sendable' has been explicitly marked unavailable here}}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
struct NS2 { // expected-note{{consider making struct 'NS2' conform to the 'Sendable' protocol}}
|
|
var ns1: NS1
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
struct NS3 { }
|
|
|
|
@available(SwiftStdlib 5.3, *)
|
|
extension NS3: Sendable { }
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
class NS4 { } // expected-note{{class 'NS4' does not conform to the 'Sendable' protocol}}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func acceptCV<T: Sendable>(_: T) { }
|
|
|
|
func acceptSendableFn(_: @Sendable @escaping () -> Void) { }
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func testCV(
|
|
ns1: NS1, ns1array: [NS1], ns2: NS2, ns3: NS3, ns4: NS4,
|
|
fn: @escaping () -> Void
|
|
// expected-note@-1{{parameter 'fn' is implicitly non-sendable}}
|
|
) {
|
|
acceptCV(ns1) // expected-warning{{conformance of 'NS1' to 'Sendable' is unavailable}}
|
|
acceptCV(ns1array) // expected-warning{{conformance of 'NS1' to 'Sendable' is unavailable}}
|
|
acceptCV(ns2)
|
|
acceptCV(ns3) // expected-warning{{conformance of 'NS3' to 'Sendable' is only available in macOS 11.0 or newer}}
|
|
// expected-note@-1{{add 'if #available' version check}}
|
|
acceptCV(ns4)
|
|
acceptCV(fn)
|
|
acceptSendableFn(fn) // expected-warning{{passing non-sendable parameter 'fn' to function expecting a @Sendable closure}}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func testCV(
|
|
ns1: NS1, ns1array: [NS1], ns2: NS2, ns3: NS3, ns4: NS4,
|
|
fn: @escaping () -> Void
|
|
// expected-note@-1{{parameter 'fn' is implicitly non-sendable}}
|
|
) async {
|
|
acceptCV(ns1) // expected-warning{{conformance of 'NS1' to 'Sendable' is unavailable}}
|
|
acceptCV(ns1array) // expected-warning{{conformance of 'NS1' to 'Sendable' is unavailable}}
|
|
acceptCV(ns2) // expected-warning{{type 'NS2' does not conform to the 'Sendable' protocol}}
|
|
acceptCV(ns3) // expected-warning{{conformance of 'NS3' to 'Sendable' is only available in macOS 11.0 or newer}}
|
|
// expected-note@-1{{add 'if #available' version check}}
|
|
acceptCV(ns4) // expected-warning{{type 'NS4' does not conform to the 'Sendable' protocol}}
|
|
acceptCV(fn) // expected-warning{{type '() -> Void' does not conform to the 'Sendable' protocol}}
|
|
// expected-note@-1{{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
acceptSendableFn(fn) // expected-warning{{passing non-sendable parameter 'fn' to function expecting a @Sendable closure}}
|
|
}
|
|
|
|
// rdar://83942484 - spurious Sendable diagnostics
|
|
@available(SwiftStdlib 5.1, *)
|
|
public protocol MyProto {
|
|
func foo<F>(aFoo: F) async where F: Sendable
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func nonisolatedAsyncFunc1(_: NS1) async { }
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func nonisolatedAsyncFunc2() async -> NS1 { NS1() }
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
public actor MyActor: MyProto {
|
|
public func foo<F>(aFoo: F) async where F: Sendable { }
|
|
public func bar<B>(aBar: B) async where B: Sendable { }
|
|
|
|
func g(ns1: NS1) async {
|
|
await nonisolatedAsyncFunc1(ns1) // expected-warning{{passing argument of non-sendable type 'NS1' outside of actor-isolated context may introduce data races}}
|
|
_ = await nonisolatedAsyncFunc2() // expected-warning{{non-sendable type 'NS1' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary}}
|
|
}
|
|
}
|
|
|
|
// rdar://82452688 - make sure sendable checking doesn't fire for a capture
|
|
// of a value of error-type
|
|
@available(SwiftStdlib 5.1, *)
|
|
func f() async {
|
|
let n = wobble() // expected-error{{cannot find 'wobble' in scope}}
|
|
@Sendable func nested() {
|
|
n.pointee += 1
|
|
}
|
|
}
|
|
|
|
// Make sure the generic signature doesn't minimize away Sendable requirements.
|
|
@_nonSendable class NSClass { }
|
|
|
|
struct WrapClass<T: NSClass> {
|
|
var t: T
|
|
}
|
|
|
|
extension WrapClass: Sendable where T: Sendable { }
|
|
|
|
// Make sure we don't inherit the unavailable Sendable conformance from
|
|
// our superclass.
|
|
class SendableSubclass: NSClass, @unchecked Sendable { }
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func testSubclassing(obj: SendableSubclass) async {
|
|
acceptCV(obj) // okay!
|
|
}
|
|
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
protocol P {
|
|
func foo (x : @Sendable () -> ()) async -> ()
|
|
|
|
func bar(x : () -> ()) async -> ()
|
|
// expected-note@-1 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
|
|
func foo2<T : Sendable>(x : T) async -> ()
|
|
|
|
func bar2<T>(x : T) async -> ()
|
|
// expected-note@-1 {{consider making generic parameter 'T' conform to the 'Sendable' protocol}}
|
|
}
|
|
|
|
// Make sure conformance to protocols checks sendability of
|
|
// requirement parameters not witness parameters
|
|
@available(SwiftStdlib 5.1, *)
|
|
actor A : P {
|
|
func foo(x : () -> ()) -> () {}
|
|
|
|
func bar(x : () -> ()) -> () {}
|
|
// expected-warning@-1 {{non-sendable type '() -> ()' in parameter of the protocol requirement satisfied by actor-isolated instance method 'bar(x:)' cannot cross actor boundary}}
|
|
|
|
func foo2<T>(x : T) -> () {}
|
|
|
|
func bar2<T>(x : T) -> () {}
|
|
// expected-warning@-1 {{non-sendable type 'T' in parameter of the protocol requirement satisfied by actor-isolated instance method 'bar2(x:)' cannot cross actor boundary}}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
class Super {
|
|
@MainActor
|
|
func foo (x : @Sendable () -> ()) async {}
|
|
|
|
@MainActor
|
|
func bar (x : () -> ()) async {}
|
|
// expected-note@-1 {{a function type must be marked '@Sendable' to conform to 'Sendable'}}
|
|
|
|
@MainActor
|
|
func foo2<T : Sendable>(x: T) async {}
|
|
|
|
@MainActor
|
|
func bar2<T>(x: T) async {}
|
|
// expected-note@-1 {{consider making generic parameter 'T' conform to the 'Sendable' protocol}}
|
|
}
|
|
|
|
// Make sure isolation crossing overrides check sendability
|
|
// of superclass parameters not subclass parameters
|
|
@available(SwiftStdlib 5.1, *)
|
|
class Sub : Super {
|
|
override nonisolated func foo(x : () -> ()) async {}
|
|
|
|
override nonisolated func bar(x : () -> ()) async {}
|
|
// expected-warning@-1 {{non-sendable type '() -> ()' in parameter of superclass method overridden by nonisolated instance method 'bar(x:)' cannot cross actor boundary}}
|
|
|
|
override nonisolated func foo2<T>(x: T) async {}
|
|
|
|
override nonisolated func bar2<T>(x: T) async {}
|
|
// expected-warning@-1 {{non-sendable type 'T' in parameter of superclass method overridden by nonisolated instance method 'bar2(x:)' cannot cross actor boundary}}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
class SuperWSafeSubscript {
|
|
@MainActor
|
|
subscript<T : Sendable>(x : T) -> Int {
|
|
get async {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
class SubWSafeSubscript : SuperWSafeSubscript {
|
|
override nonisolated subscript<T>(x : T) -> Int {
|
|
get async {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
class SuperWUnsafeSubscript {
|
|
@MainActor
|
|
subscript<T>(x : T) -> Int {
|
|
// expected-note@-1 2{{consider making generic parameter 'T' conform to the 'Sendable' protocol}}
|
|
get async {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
class SubWUnsafeSubscript : SuperWUnsafeSubscript {
|
|
override nonisolated subscript<T>(x : T) -> Int {
|
|
get async {
|
|
// expected-warning@-2{{non-sendable type 'T' in parameter of superclass method overridden by nonisolated subscript 'subscript(_:)' cannot cross actor boundary}}
|
|
// expected-warning@-2{{non-sendable type 'T' in parameter of superclass method overridden by nonisolated getter for subscript 'subscript(_:)' cannot cross actor boundary}}
|
|
// there really shouldn't be two warnings produced here, see rdar://110846040 (Sendable diagnostics reported twice for subscript getters)
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Test implicit conversions getting in the way
|
|
@available(SwiftStdlib 5.1, *)
|
|
extension MyActor {
|
|
func f(_: Any) { }
|
|
func g(_: () -> Void) { }
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func testConversionsAndSendable(a: MyActor, s: any Sendable, f: @Sendable () -> Void) async {
|
|
await a.f(s)
|
|
await a.g(f)
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
final class NonSendable {
|
|
// expected-note@-1 3 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
|
|
var value = ""
|
|
|
|
@MainActor
|
|
func update() {
|
|
value = "update"
|
|
}
|
|
|
|
func call() async {
|
|
await update()
|
|
// expected-warning@-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
|
|
|
|
await self.update()
|
|
// expected-warning@-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.1, *)
|
|
func testNonSendableBaseArg() async {
|
|
let t = NonSendable()
|
|
await t.update()
|
|
// expected-warning@-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
|
|
}
|