Skip to content

Commit fd14a97

Browse files
committed
[region-isolation] Ensure that global actor guarded globals are treated as being actor specific state.
So for instance, one cannot transfer them, just like actor state.
1 parent fca9747 commit fd14a97

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2924,6 +2924,17 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
29242924
iter.first->getSecond().addFlag(TrackableValueFlag::isActorDerived);
29252925
}
29262926
}
2927+
2928+
// See if the memory base is a global_addr from a global actor protected global.
2929+
if (auto *ga = dyn_cast<GlobalAddrInst>(storage.base)) {
2930+
if (auto *global = ga->getReferencedGlobal()) {
2931+
if (auto *globalDecl = global->getDecl()) {
2932+
if (getActorIsolation(globalDecl).isGlobalActor()) {
2933+
iter.first->getSecond().addFlag(TrackableValueFlag::isActorDerived);
2934+
}
2935+
}
2936+
}
2937+
}
29272938
}
29282939
}
29292940

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %target-swift-frontend -emit-sil -strict-concurrency=complete -enable-experimental-feature RegionBasedIsolation -disable-availability-checking -verify -verify-additional-prefix tns- %s -o /dev/null -parse-as-library
2+
3+
// Tests specific to global actors.
4+
5+
// REQUIRES: concurrency
6+
// REQUIRES: asserts
7+
8+
////////////////////////
9+
// MARK: Declarations //
10+
////////////////////////
11+
12+
class Klass {}
13+
14+
struct NonSendableStruct {
15+
var first = Klass()
16+
var second = Klass()
17+
}
18+
19+
func useValue<T>(_ t: T) {}
20+
func getAny() -> Any { fatalError() }
21+
22+
actor Custom {
23+
}
24+
25+
@globalActor
26+
struct CustomActor {
27+
static var shared: Custom {
28+
return Custom()
29+
}
30+
}
31+
32+
@MainActor func transferToMain<T>(_ t: T) {}
33+
@CustomActor func transferToCustom<T>(_ t: T) {}
34+
35+
@MainActor var globalKlass = Klass()
36+
37+
/////////////////
38+
// MARK: Tests //
39+
/////////////////
40+
41+
@MainActor func testTransferGlobalActorGuardedValue() async {
42+
await transferToCustom(globalKlass) // expected-tns-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}}
43+
}
44+
45+
@MainActor func testTransferGlobalActorGuardedValueWithlet() async {
46+
let x = globalKlass
47+
await transferToCustom(x) // expected-tns-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}}
48+
}
49+
50+
@MainActor func testTransferGlobalActorGuardedValueWithlet(_ k: Klass) async {
51+
globalKlass = k
52+
await transferToCustom(k) // expected-tns-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}}
53+
}

test/Concurrency/transfernonsendable_strong_transferring.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,19 @@ struct NonSendableStruct {
1515

1616
func useValue<T>(_ t: T) {}
1717
func getAny() -> Any { fatalError() }
18+
19+
actor Custom {
20+
}
21+
22+
@globalActor
23+
struct CustomActor {
24+
static var shared: Custom {
25+
return Custom()
26+
}
27+
}
28+
1829
@MainActor func transferToMain<T>(_ t: T) {}
30+
@CustomActor func transferToCustom<T>(_ t: T) {}
1931

2032
func transferArg(_ x: transferring Klass) {
2133
}
@@ -122,11 +134,27 @@ actor MyActor {
122134
globalKlass = x
123135
}
124136

137+
@MainActor func canAssignTransferringIntoGlobalActor2(_ x: transferring Klass) async {
138+
globalKlass = x
139+
await transferToCustom(x) // expected-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}}
140+
}
141+
142+
@MainActor func canAssignTransferringIntoGlobalActor3(_ x: transferring Klass) async {
143+
await transferToCustom(globalKlass) // expected-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}}
144+
}
145+
125146
func canTransferAssigningIntoLocal(_ x: transferring Klass) async {
126147
let _ = x
127148
await transferToMain(x)
128149
}
129150

151+
func canTransferAssigningIntoLocal2(_ x: transferring Klass) async {
152+
let _ = x
153+
await transferToMain(x) // expected-warning {{passing argument of non-sendable type 'Klass' from nonisolated context to main actor-isolated context at this call site could yield a race with accesses later in this function}}
154+
let _ = x // expected-note {{access here could race}}
155+
}
156+
157+
130158
//////////////////////////////////////
131159
// MARK: Transferring is "var" like //
132160
//////////////////////////////////////

0 commit comments

Comments
 (0)