Files
swift-mirror/test/Concurrency/Runtime/isolated_conformance.swift
Alastair Houghton 748ba05161 [Concurrency][Tests] Bump availability in a couple of tests.
Since we've bumped availability elsewhere, we need to bump these
tests also.
2025-11-18 12:08:46 +00:00

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)