Files
swift-mirror/test/Concurrency/actor_isolation_swift6.swift
Michael Gottesman 3ed4059a60 [sema] Change non-sendable -> non-Sendable in diagnostics.
This matches send non sendable but importantly also makes it clear that we are
talking about something that doesn't conform to the Sendable protocol which is
capitalized.

rdar://151802975
2025-05-22 11:37:58 -07:00

136 lines
4.6 KiB
Swift

// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -swift-version 6 -emit-sil -o /dev/null -verify %s
// REQUIRES: concurrency
// REQUIRES: asserts
final class ImmutablePoint: Sendable {
let x : Int = 0
let y : Int = 0
}
actor SomeActor { }
@globalActor
struct SomeGlobalActor {
static let shared = SomeActor()
}
/// ------------------------------------------------------------------
/// -- Value types do not need isolation on their stored properties --
protocol MainCounter {
@MainActor var counter: Int { get set }
@MainActor var ticker: Int { get set }
}
struct InferredFromConformance: MainCounter {
var counter = 0
var ticker: Int {
get { 1 }
set {}
}
}
@MainActor
struct InferredFromContext {
var point = ImmutablePoint()
var polygon: [ImmutablePoint] {
get { [] }
}
nonisolated let flag: Bool = false
subscript(_ i: Int) -> Int { return i }
static var stuff: [Int] = []
}
func checkIsolationValueType(_ formance: InferredFromConformance,
_ ext: InferredFromContext,
_ anno: NoGlobalActorValueType) async {
// these do not need an await, since it's a value type
_ = ext.point
_ = formance.counter
_ = anno.counter
// make sure it's just a warning if someone was awaiting on it previously
_ = await ext.point // expected-warning {{no 'async' operations occur within 'await' expression}}
_ = await formance.counter // expected-warning {{no 'async' operations occur within 'await' expression}}
_ = await anno.counter // expected-warning {{no 'async' operations occur within 'await' expression}}
// this does not need an await, since the property is 'Sendable' and of a
// value type
_ = anno.point
_ = await anno.point
// expected-warning@-1 {{no 'async' operations occur within 'await' expression}}
// these do need await, regardless of reference or value type
_ = await (formance as any MainCounter).counter
// expected-error@-1 {{non-Sendable type 'any MainCounter' cannot be sent into main actor-isolated context in call to property 'counter'}}
_ = await ext[1]
_ = await formance.ticker
_ = await ext.polygon
_ = await InferredFromContext.stuff
_ = await NoGlobalActorValueType.polygon
}
struct NoGlobalActorValueType {
@SomeGlobalActor var point: ImmutablePoint
@MainActor let counter: Int
@MainActor static var polygon: [ImmutablePoint] = []
}
/// -----------------------------------------------------------------
@MainActor
class MainActorIsolated {
init() {}
// expected-note@+1 {{static property declared here}}
static let shared = MainActorIsolated()
}
nonisolated func accessAcrossActors() {
// expected-error@+1 {{main actor-isolated static property 'shared' can not be referenced from a nonisolated context}}
let _ = MainActorIsolated.shared
}
struct ReferenceSelfDotMethods {
@MainActor
func mainActorAffinedFunction() {}
nonisolated
private func testCurry() -> (Self) -> (@MainActor () -> Void) {
let functionRef = Self.mainActorAffinedFunction
return functionRef
}
@MainActor
private func callOnMainActorOk() {
let mainActorAffinedClosure = testCurry()(self)
mainActorAffinedClosure()
}
nonisolated
private func nonisolatedCallErrors() {
let mainActorAffinedClosure = testCurry()(self)
// expected-note@-1 {{calls to let 'mainActorAffinedClosure' from outside of its actor context are implicitly asynchronous}}
mainActorAffinedClosure()
// expected-error@-1 {{call to main actor-isolated let 'mainActorAffinedClosure' in a synchronous nonisolated context}}
}
}
actor UserDefinedActorSelfDotMethod {
func actorAffinedFunc() {} // expected-note {{calls to instance method 'actorAffinedFunc()' from outside of its actor context are implicitly asynchronous}}
// Unfortunately we can't express the desired isolation of this returned closure statically to
// be able to call it on the desired actor. This may be possible with the acceptance of
// https://forums.swift.org/t/closure-isolation-control/70378 but I think we need more expressivity
// in the type system to express this sort of curry.
nonisolated
private func testCurry() -> (UserDefinedActorSelfDotMethod) -> (@isolated(any) () -> Void) {
let functionRef = Self.actorAffinedFunc // expected-error {{call to actor-isolated instance method 'actorAffinedFunc()' in a synchronous nonisolated context}}
return functionRef // expected-error {{cannot convert return expression of type '@Sendable (isolated Self) -> @Sendable () -> ()' to return type '(UserDefinedActorSelfDotMethod) -> @isolated(any) () -> Void'}}
}
}