Skip to content

Commit 00f1e1e

Browse files
committed
[region-isolation] Make it so that we only propagate actor self if the callee takes self as isolated.
rdar://121387872
1 parent 6f3d452 commit 00f1e1e

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,10 +1619,14 @@ class PartitionOpTranslator {
16191619

16201620
void translateNonIsolationCrossingSILApply(FullApplySite fas) {
16211621
SILMultiAssignOptions options;
1622+
1623+
// If self is an actor and we are isolated to it, propagate actor self.
16221624
if (fas.hasSelfArgument()) {
1623-
if (auto self = fas.getSelfArgument()) {
1624-
if (self->getType().isActor())
1625-
options |= SILMultiAssignFlags::PropagatesActorSelf;
1625+
auto &self = fas.getSelfArgumentOperand();
1626+
if (self.get()->getType().isActor() &&
1627+
fas.getArgumentParameterInfo(self).hasOption(
1628+
SILParameterInfo::Isolated)) {
1629+
options |= SILMultiAssignFlags::PropagatesActorSelf;
16261630
}
16271631
}
16281632

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %target-swift-frontend -emit-sil -strict-concurrency=complete -enable-experimental-feature RegionBasedIsolation -disable-availability-checking -verify %s -o /dev/null
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: asserts
5+
6+
// This test validates behavior of transfernonsendable around nonisolated
7+
// functions and fields.
8+
9+
////////////////////////
10+
// MARK: Declarations //
11+
////////////////////////
12+
13+
class NonSendable {}
14+
15+
actor MyActor {
16+
nonisolated func asyncNonisolated(_ x: NonSendable) async {}
17+
nonisolated func syncNonisolated(_ x: NonSendable) {}
18+
nonisolated func asyncNonisolatedGeneric<T>(_ t: T) async {}
19+
nonisolated func syncNonisolatedGeneric<T>(_ t: T) {}
20+
}
21+
22+
@MainActor func transferToMain<T>(_ t: T) async {}
23+
func useValueAsync<T>(_ t: T) async {}
24+
func useValueSync<T>(_ t: T) {}
25+
26+
/////////////////
27+
// MARK: Tests //
28+
/////////////////
29+
30+
func callNonIsolatedAsync_TransferAfter(_ a: MyActor) async {
31+
let x = NonSendable()
32+
await a.asyncNonisolated(x)
33+
await a.asyncNonisolated(x)
34+
await transferToMain(x)
35+
}
36+
37+
func callNonIsolatedSync_TransferAfter(_ a: MyActor) async {
38+
let x = NonSendable()
39+
a.syncNonisolated(x)
40+
a.syncNonisolated(x)
41+
await transferToMain(x)
42+
}
43+
44+
func callNonIsolatedAsync_AsyncUseAfter(_ a: MyActor) async {
45+
let x = NonSendable()
46+
await a.asyncNonisolated(x)
47+
await a.asyncNonisolated(x)
48+
await useValueAsync(x)
49+
}
50+
51+
func callNonIsolatedSync_AsyncUseAfter(_ a: MyActor) async {
52+
let x = NonSendable()
53+
a.syncNonisolated(x)
54+
a.syncNonisolated(x)
55+
await useValueAsync(x)
56+
}
57+
58+
func callNonIsolatedAsync_SyncUseAfter(_ a: MyActor) async {
59+
let x = NonSendable()
60+
await a.asyncNonisolated(x)
61+
await a.asyncNonisolated(x)
62+
useValueSync(x)
63+
}
64+
65+
func callNonIsolatedSync_SyncUseAfter(_ a: MyActor) async {
66+
let x = NonSendable()
67+
a.syncNonisolated(x)
68+
a.syncNonisolated(x)
69+
useValueSync(x)
70+
}

0 commit comments

Comments
 (0)