Skip to content

Commit 05df552

Browse files
committed
[rbi] When translating a Store, make sure to require src even if the value being stored is Sendable
This is important to ensure that we require the base of src if the src is non-Sendable (e.x.: a non-Sendable box). rdar://163322459 #85107 (cherry picked from commit 3f180c6)
1 parent efbd1af commit 05df552

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2982,7 +2982,7 @@ class PartitionOpTranslator {
29822982
/// dest to src. If the \p dest could be aliased, then we must instead treat
29832983
/// them as merges, to ensure any aliases of \p dest are also updated.
29842984
void translateSILStore(Operand *dest, Operand *src,
2985-
SILIsolationInfo resultIsolationInfoOverride = {}) {
2985+
SILIsolationInfo resultIsolationInfoOverride = {}) {
29862986
SILValue destValue = dest->get();
29872987

29882988
if (auto destResult = tryToTrackValue(destValue)) {
@@ -3010,7 +3010,14 @@ class PartitionOpTranslator {
30103010
resultIsolationInfoOverride);
30113011
}
30123012

3013-
// Stores to storage of non-Sendable type can be ignored.
3013+
// If we reached this point, our destination is something that is Sendable
3014+
// and is not an address that comes from a non-Sendable base... so we can
3015+
// ignore the store part. But we still need tosee if our src (which also
3016+
// must be Sendable) comes from a non-Sendable base. In such a case, we need
3017+
// to require that.
3018+
if (auto srcResult = tryToTrackValue(src->get())) {
3019+
builder.addRequire(*srcResult);
3020+
}
30143021
}
30153022

30163023
void translateSILTupleAddrConstructor(TupleAddrConstructorInst *inst) {

test/Concurrency/transfernonsendable.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,3 +2019,36 @@ func avoidThinkingClosureParameterIsSending() {
20192019
}
20202020
}
20212021
}
2022+
2023+
enum RequireSrcWhenStoringEvenWhenSendable {
2024+
func test<T: Sendable>(t: T) {
2025+
var result: T = t
2026+
Task { // expected-warning {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
2027+
// expected-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code}}
2028+
result = t
2029+
}
2030+
useValue(result) // expected-note {{access can happen concurrently}}
2031+
}
2032+
2033+
func test2() {
2034+
var result: Any = 0
2035+
Task { // expected-warning {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
2036+
// expected-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code}}
2037+
result = 0
2038+
}
2039+
useValue(result) // expected-note {{access can happen concurrently}}
2040+
}
2041+
2042+
protocol Initializable {
2043+
init()
2044+
}
2045+
2046+
func test3<T: Initializable & SendableMetatype>(type: T.Type) {
2047+
var result = type.init()
2048+
Task { // expected-warning {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
2049+
// expected-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code}}
2050+
result = type.init()
2051+
}
2052+
useValue(result) // expected-note {{access can happen concurrently}}
2053+
}
2054+
}

0 commit comments

Comments
 (0)