-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathactor_isolation_swift6.swift
136 lines (109 loc) · 4.56 KB
/
actor_isolation_swift6.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// 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'}}
}
}