mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
227 lines
5.0 KiB
Swift
227 lines
5.0 KiB
Swift
// RUN: %target-run-simple-swift(-target %target-swift-5.1-abi-triple) | %FileCheck %s
|
|
// RUN: %target-run-simple-swift(-target %target-swift-5.1-abi-triple -swift-version 5 -strict-concurrency=complete -enable-upcoming-feature NonisolatedNonsendingByDefault) | %FileCheck %s
|
|
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
|
|
|
|
// REQUIRES: executable_test
|
|
// REQUIRES: concurrency
|
|
// REQUIRES: concurrency_runtime
|
|
// UNSUPPORTED: back_deployment_runtime
|
|
|
|
protocol P {
|
|
func f()
|
|
}
|
|
|
|
protocol Q {
|
|
func g()
|
|
}
|
|
|
|
protocol R: Sendable {
|
|
func h()
|
|
}
|
|
|
|
nonisolated class MyClass: @MainActor P {
|
|
func f() {
|
|
print("MyClass.f()")
|
|
|
|
// Make sure we're on the main actor.
|
|
MainActor.assumeIsolated { }
|
|
}
|
|
}
|
|
|
|
actor SomeActor { }
|
|
|
|
@globalActor
|
|
struct SomeGlobalActor {
|
|
static let shared = SomeActor()
|
|
}
|
|
|
|
extension MyClass: @SomeGlobalActor Q {
|
|
@SomeGlobalActor func g() {
|
|
print("MyClass.g()")
|
|
|
|
// Make sure we're on this actor.
|
|
SomeGlobalActor.shared.assumeIsolated { _ in }
|
|
}
|
|
}
|
|
|
|
extension MyClass: nonisolated R {
|
|
nonisolated func h() {
|
|
print("MyClass.h()")
|
|
}
|
|
}
|
|
|
|
struct Wrapper<T> {
|
|
var wrapped: T
|
|
}
|
|
|
|
extension Wrapper: P where T: P {
|
|
func f() {
|
|
print("Wrapper for ", terminator: "")
|
|
wrapped.f()
|
|
}
|
|
}
|
|
|
|
extension Wrapper: Q where T: Q {
|
|
func g() {
|
|
print("Wrapper for ", terminator: "")
|
|
wrapped.g()
|
|
}
|
|
}
|
|
|
|
extension Wrapper: R where T: R {
|
|
func h() {
|
|
print("Wrapper for ", terminator: "")
|
|
wrapped.h()
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.9, *)
|
|
struct WrapMany<each T> {
|
|
var wrapped: (repeat each T)
|
|
}
|
|
|
|
@available(SwiftStdlib 5.9, *)
|
|
extension WrapMany: P where repeat each T: P {
|
|
func f() {
|
|
print("Wrapper for many")
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.9, *)
|
|
extension WrapMany: Q where repeat each T: Q {
|
|
func g() {
|
|
print("Wrapper for many")
|
|
}
|
|
}
|
|
|
|
@available(SwiftStdlib 5.9, *)
|
|
extension WrapMany: R where repeat each T: R {
|
|
func h() {
|
|
print("Wrapper for many")
|
|
}
|
|
}
|
|
|
|
extension Int: P, Q, R {
|
|
func f() { }
|
|
func g() { }
|
|
func h() { }
|
|
}
|
|
|
|
extension String: P, Q, R {
|
|
func f() { }
|
|
func g() { }
|
|
func h() { }
|
|
}
|
|
|
|
func tryCastToP(_ value: any Sendable) -> Bool {
|
|
if let p = value as? any P {
|
|
p.f()
|
|
return true
|
|
}
|
|
|
|
print("Conformance did not match")
|
|
return false
|
|
}
|
|
|
|
func tryCastToPAndR(_ value: any Sendable) -> Bool {
|
|
if let p = value as? any P & R {
|
|
p.f()
|
|
return true
|
|
}
|
|
|
|
print("Conformance did not match")
|
|
return false
|
|
}
|
|
|
|
func tryCastToQ(_ value: any Sendable) -> Bool {
|
|
if let q = value as? any Q {
|
|
q.g()
|
|
return true
|
|
}
|
|
|
|
print("Conformance did not match")
|
|
return false
|
|
}
|
|
|
|
// CHECK: Testing on the main actor
|
|
// CHECK-NEXT: MyClass.f()
|
|
// CHECK-NEXT: Wrapper for MyClass.f()
|
|
print("Testing on the main actor")
|
|
nonisolated let mc = MyClass()
|
|
nonisolated let wrappedMC = Wrapper(wrapped: mc)
|
|
precondition(tryCastToP(mc))
|
|
precondition(tryCastToP(wrappedMC))
|
|
|
|
if #available(SwiftStdlib 5.9, *) {
|
|
let wrappedMany = WrapMany(wrapped: (17, mc, "Pack"))
|
|
precondition(tryCastToP(wrappedMany))
|
|
}
|
|
|
|
// CHECK: Testing a separate task on the main actor
|
|
// CHECK-NEXT: MyClass.f()
|
|
// CHECK-NEXT: Wrapper for MyClass.f()
|
|
print("Testing a separate task on the main actor")
|
|
await Task.detached { @MainActor in
|
|
precondition(tryCastToP(mc))
|
|
precondition(tryCastToP(wrappedMC))
|
|
|
|
// Cannot cast to P & R because the conformance to P is isolated, but R
|
|
// is Sendable.
|
|
precondition(!tryCastToPAndR(mc))
|
|
precondition(!tryCastToPAndR(wrappedMC))
|
|
|
|
if #available(SwiftStdlib 5.9, *) {
|
|
let wrappedMany = WrapMany(wrapped: (17, mc, "Pack"))
|
|
precondition(tryCastToP(wrappedMany))
|
|
}
|
|
|
|
}.value
|
|
|
|
// CHECK: Testing a separate task on a different global actor
|
|
// CHECK-NEXT: MyClass.g()
|
|
// CHECK-NEXT: Wrapper for MyClass.g()
|
|
print("Testing a separate task on a different global actor")
|
|
await Task.detached { @SomeGlobalActor in
|
|
precondition(tryCastToQ(mc))
|
|
precondition(tryCastToQ(wrappedMC))
|
|
|
|
// Cannot cast to P & R because the conformance to P is isolated, but R
|
|
// is Sendable.
|
|
precondition(!tryCastToPAndR(mc))
|
|
precondition(!tryCastToPAndR(wrappedMC))
|
|
|
|
if #available(SwiftStdlib 5.9, *) {
|
|
let wrappedMany = WrapMany(wrapped: (17, mc, "Pack"))
|
|
precondition(tryCastToQ(wrappedMany))
|
|
}
|
|
|
|
// Not on the main actor any more.
|
|
precondition(!tryCastToP(mc))
|
|
precondition(!tryCastToP(wrappedMC))
|
|
}.value
|
|
|
|
// CHECK: Testing a separate task off the main actor
|
|
print("Testing a separate task off the main actor")
|
|
await Task.detached {
|
|
if #available(SwiftStdlib 6.3, *) {
|
|
// Skip tests on platforms that use the same executor for the main
|
|
// actor and the global concurrent executor.
|
|
guard Task.defaultExecutor !== MainActor.executor else { return }
|
|
|
|
precondition(!tryCastToP(mc))
|
|
precondition(!tryCastToP(wrappedMC))
|
|
|
|
precondition(!tryCastToQ(mc))
|
|
precondition(!tryCastToQ(wrappedMC))
|
|
|
|
let wrappedMany = WrapMany(wrapped: (17, mc, "Pack"))
|
|
precondition(!tryCastToP(wrappedMany))
|
|
} else {
|
|
print("Cast succeeds, but shouldn't")
|
|
}
|
|
}.value
|
|
|
|
|
|
// Ensure that we access mc later
|
|
print(mc)
|