Skip to content

Commit c72e57e

Browse files
authored
Merge pull request #80911 from gottesmm/pr-52ba504b4ba7185b4e3f34ed03b36721f4ad3d82
[rbi] Simplify some logic that got confused so that passing an actor isolated value to a callee that is isolated ot the same actor is not considered a send.
2 parents f0430eb + 205038b commit c72e57e

File tree

4 files changed

+46
-17
lines changed

4 files changed

+46
-17
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,15 +1438,18 @@ struct PartitionOpEvaluator {
14381438
}
14391439
std::tie(sentRegionIsolation, regionHasClosureCapturedElt) = *pairOpt;
14401440

1441-
// If we merged anything, we need to handle an attempt to send a
1442-
// never-sent value unless our value has the same isolation info as our
1443-
// callee.
14441441
auto calleeIsolationInfo = getIsolationInfo(op);
1445-
if (!(calleeIsolationInfo &&
1446-
sentRegionIsolation.hasSameIsolation(calleeIsolationInfo)) &&
1447-
!sentRegionIsolation.isDisconnected()) {
1448-
return handleSendNeverSentHelper(op, op.getOpArg1(),
1449-
sentRegionIsolation);
1442+
1443+
// If our callee and region are both actor isolated and part of the same
1444+
// isolation domain, do not treat this as a send.
1445+
if (calleeIsolationInfo.isActorIsolated() &&
1446+
sentRegionIsolation.hasSameIsolation(calleeIsolationInfo))
1447+
return;
1448+
1449+
// At this point, check if our sent value is not disconnected. If so, emit
1450+
// a sent never sendable helper.
1451+
if (sentRegionIsolation && !sentRegionIsolation.isDisconnected()) {
1452+
return handleSendNeverSentHelper(op, op.getOpArg1(), sentRegionIsolation);
14501453
}
14511454

14521455
// Next see if we are disconnected and have the same isolation. In such a

test/Concurrency/concurrent_value_checking.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,8 @@ func globalTest() async {
141141
// expected-warning@+2 {{expression is 'async' but is not marked with 'await'}}
142142
// expected-note@+1 {{property access is 'async'}}
143143
let a = globalValue // expected-warning{{non-sendable type 'NotConcurrent?' of let 'globalValue' cannot exit global actor 'SomeGlobalActor'-isolated context}}
144-
await globalAsync(a) // expected-tns-warning {{sending 'a' risks causing data races}}
145-
// expected-tns-note @-1 {{sending global actor 'SomeGlobalActor'-isolated 'a' to global actor 'SomeGlobalActor'-isolated global function 'globalAsync' risks causing data races between global actor 'SomeGlobalActor'-isolated and local nonisolated uses}}
146-
await globalSync(a) // expected-tns-note {{access can happen concurrently}}
144+
await globalAsync(a)
145+
await globalSync(a)
147146

148147
// expected-warning@+2 {{expression is 'async' but is not marked with 'await'}}
149148
// expected-note@+1 {{property access is 'async'}}
@@ -178,9 +177,8 @@ func globalTestMain(nc: NotConcurrent) async {
178177
// expected-warning@+2 {{expression is 'async' but is not marked with 'await'}}
179178
// expected-note@+1 {{property access is 'async'}}
180179
let a = globalValue // expected-warning {{non-sendable type 'NotConcurrent?' of let 'globalValue' cannot exit global actor 'SomeGlobalActor'-isolated context}}
181-
await globalAsync(a) // expected-tns-warning {{sending 'a' risks causing data races}}
182-
// expected-tns-note @-1 {{sending global actor 'SomeGlobalActor'-isolated 'a' to global actor 'SomeGlobalActor'-isolated global function 'globalAsync' risks causing data races between global actor 'SomeGlobalActor'-isolated and local main actor-isolated uses}}
183-
await globalSync(a) // expected-tns-note {{access can happen concurrently}}
180+
await globalAsync(a)
181+
await globalSync(a)
184182
_ = await ClassWithGlobalActorInits(nc)
185183
// expected-tns-warning @-1 {{non-Sendable 'ClassWithGlobalActorInits'-typed result can not be returned from global actor 'SomeGlobalActor'-isolated initializer 'init(_:)' to main actor-isolated context}}
186184
// expected-tns-warning @-2 {{sending 'nc' risks causing data races}}

test/Concurrency/transfernonsendable.sil

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,14 @@ bb0:
158158
%f = function_ref @transferIndirectWithOutResult : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
159159
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<NonSendableKlass>(%1, %0) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0 // expected-warning {{}}
160160

161+
// We do not error here on use after send since %1 is already isolated to the
162+
// same global actor as transferIndirect which is not considered to be a
163+
// send. We leave the actual error to be the error about returning an isolated
164+
// value into a non-isolated context.
161165
%f2 = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
162166
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f2<NonSendableKlass>(%1) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
163-
// expected-warning @-1 {{}}
164-
// expected-note @-2 {{}}
165167
%useIndirect = function_ref @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
166168
apply %useIndirect<NonSendableKlass>(%1) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
167-
// expected-note @-1 {{access can happen concurrently}}
168169

169170
destroy_addr %1 : $*NonSendableKlass
170171
dealloc_stack %1 : $*NonSendableKlass

test/Concurrency/transfernonsendable.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,3 +2027,30 @@ func testIsolatedParamInference() {
20272027
}
20282028
}
20292029
}
2030+
2031+
// We shouldn't error here since test2 is isolated to B since we are capturing
2032+
// self and funcParam is also exposed to B's isolated since it is a parameter to
2033+
// one of B's methods.
2034+
func sendIsolatedValueToItsOwnIsolationDomain() {
2035+
class A {
2036+
func useValue() {}
2037+
}
2038+
2039+
func helper(_ x: @escaping () -> A) {}
2040+
2041+
actor B {
2042+
let field = A()
2043+
2044+
private func test(funcParam: A?) async {
2045+
helper {
2046+
if let funcParam {
2047+
return funcParam
2048+
} else {
2049+
return self.field
2050+
}
2051+
}
2052+
2053+
funcParam?.useValue()
2054+
}
2055+
}
2056+
}

0 commit comments

Comments
 (0)