File tree Expand file tree Collapse file tree 2 files changed +38
-2
lines changed Expand file tree Collapse file tree 2 files changed +38
-2
lines changed Original file line number Diff line number Diff line change @@ -924,9 +924,17 @@ namespace {
924
924
case ActorIsolationRestriction::Unrestricted:
925
925
case ActorIsolationRestriction::LocalCapture:
926
926
case ActorIsolationRestriction::Unsafe:
927
- case ActorIsolationRestriction::GlobalActor: // TODO: handle global
928
- // actors
929
927
break ;
928
+ case ActorIsolationRestriction::GlobalActor: {
929
+ ctx.Diags .diagnose (call->getLoc (),
930
+ diag::actor_isolated_inout_state,
931
+ valueDecl->getDescriptiveKind (),
932
+ valueDecl->getName (),
933
+ call->implicitlyAsync ());
934
+ valueDecl->diagnose (diag::kind_declared_here,
935
+ valueDecl->getDescriptiveKind ());
936
+ return true ;
937
+ }
930
938
case ActorIsolationRestriction::ActorSelf: {
931
939
if (isPartialApply) {
932
940
// The partially applied InoutArg is a property of actor. This can
Original file line number Diff line number Diff line change @@ -131,3 +131,31 @@ extension TestActor {
131
131
await other. modify ( & value2)
132
132
}
133
133
}
134
+
135
+ // Verify global actor protection
136
+
137
+ @globalActor
138
+ struct MyGlobalActor {
139
+ static let shared = TestActor ( )
140
+ }
141
+
142
+ @MyGlobalActor var number : Int = 0
143
+ // expected-note@-1{{var declared here}}
144
+ // expected-note@-2{{var declared here}}
145
+ // expected-note@-3{{mutable state is only available within the actor instance}}
146
+
147
+ // expected-error@+2{{actor-isolated var 'number' cannot be passed 'inout' to 'async' function call}}
148
+ // expected-error@+1{{var 'number' isolated to global actor 'MyGlobalActor' can not be referenced from this context}}
149
+ let _ = Task . runDetached { await { ( _ foo: inout Int ) async in foo += 1 } ( & number) }
150
+
151
+ // attempt to pass global state owned by the global actor to another async function
152
+ // expected-error@+1{{actor-isolated var 'number' cannot be passed 'inout' to 'async' function call}}
153
+ @MyGlobalActor func sneaky( ) async { await modifyAsynchronously ( & number) }
154
+
155
+ // It's okay to pass actor state inout to synchronous functions!
156
+
157
+ func globalSyncFunction( _ foo: inout Int ) { }
158
+ @MyGlobalActor func globalActorSyncFunction( _ foo: inout Int ) { }
159
+ @MyGlobalActor func globalActorAsyncOkay( ) async { globalActorSyncFunction ( & number) }
160
+ @MyGlobalActor func globalActorAsyncOkay2( ) async { globalSyncFunction ( & number) }
161
+ @MyGlobalActor func globalActorSyncOkay( ) { globalSyncFunction ( & number) }
You can’t perform that action at this time.
0 commit comments