Skip to content

Commit 13ef2a0

Browse files
authored
Merge pull request #86151 from gottesmm/pr-9798df40033186940bfad19e0ff54d20221159e7
[rbi] Add a special diagnostic for when emitting error for a non-Sendable mutable box escaping from one concurrency domaint to another.
2 parents ffcba97 + 6de44f4 commit 13ef2a0

File tree

4 files changed

+54
-13
lines changed

4 files changed

+54
-13
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,8 @@ NOTE(regionbasedisolation_named_value_used_after_explicit_sending, none,
10561056
NOTE(regionbasedisolation_named_isolated_closure_yields_race, none,
10571057
"%select{%1 |}0%2 is captured by a %3 closure. %3 uses in closure may race against later %4 uses",
10581058
(bool, StringRef, Identifier, StringRef, StringRef))
1059+
NOTE(regionbasedisolation_named_isolated_closure_yields_race_mutable, none,
1060+
"%0 closure captures reference to mutable %1 which remains modifiable by %select{%3 code|code in the current task}2", (StringRef, Identifier, bool, StringRef))
10591061

10601062
NOTE(regionbasedisolation_typed_use_after_sending, none,
10611063
"Passing value of non-Sendable type %0 as a 'sending' argument risks causing races in between local and caller code",
@@ -1096,7 +1098,7 @@ NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_value_
10961098
"closure captures %0 which is accessible to code in the current task",
10971099
(DeclName))
10981100
NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_boxed_value_task_isolated, none,
1099-
"closure captures reference to mutable %kind0 which is accessible to code in the current task",
1101+
"closure captures reference to mutable %kind0 which remains modifiable by code in the current task",
11001102
(const ValueDecl *))
11011103
NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_value_region, none,
11021104
"closure captures %1 which is accessible to %0 code",

lib/SILOptimizer/Mandatory/SendNonSendable.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,24 @@ class SendNeverSentDiagnosticEmitter {
16681668
callerIsolationStr);
16691669
}
16701670

1671+
void
1672+
emitNamedFunctionArgumentClosureMutable(SILLocation loc, Identifier name,
1673+
ApplyIsolationCrossing crossing) {
1674+
emitNamedOnlyError(loc, name);
1675+
1676+
auto calleeIsolationStr =
1677+
SILIsolationInfo::printActorIsolationForDiagnostics(
1678+
getFunction(), crossing.getCalleeIsolation());
1679+
auto callerIsolationStr =
1680+
SILIsolationInfo::printActorIsolationForDiagnostics(
1681+
getFunction(), crossing.getCallerIsolation());
1682+
diagnoseNote(
1683+
loc,
1684+
diag::regionbasedisolation_named_isolated_closure_yields_race_mutable,
1685+
calleeIsolationStr, name, getIsolationRegionInfo()->isTaskIsolated(),
1686+
callerIsolationStr);
1687+
}
1688+
16711689
void emitTypedSendingNeverSendableToSendingParam(SILLocation loc,
16721690
Type inferredType) {
16731691
diagnoseError(loc, diag::regionbasedisolation_type_send_yields_race,
@@ -2104,6 +2122,27 @@ bool SentNeverSendableDiagnosticInferrer::initForIsolatedPartialApply(
21042122
// going to be returning some form of a SILFunctionArgument which is always
21052123
// easy to find a name for.
21062124
if (auto rootValueAndName = inferNameAndRootHelper(op->get())) {
2125+
// See if our underlying value is a SILBox type that contains a Sendable
2126+
// type. In that case, we could have only emitted this error if we were
2127+
// escaping the box itself. In such a case, we want to emit a better
2128+
// diagnostic that mentions that the reason we are emitting an error is b/c
2129+
// the value is mutable.
2130+
if (auto boxTy = op->get()->getType().getAs<SILBoxType>();
2131+
boxTy && boxTy->getLayout()->isMutable() &&
2132+
llvm::all_of(boxTy->getLayout()->getFields(),
2133+
[&op](const SILField &field) -> bool {
2134+
auto fieldTy = field.getAddressType();
2135+
if (fieldTy.hasTypeParameter())
2136+
fieldTy =
2137+
op->getFunction()->mapTypeIntoEnvironment(fieldTy);
2138+
return SILIsolationInfo::isSendableType(
2139+
fieldTy, op->getFunction());
2140+
})) {
2141+
diagnosticEmitter.emitNamedFunctionArgumentClosureMutable(
2142+
diagnosticOp->getUser()->getLoc(), rootValueAndName->first, crossing);
2143+
return true;
2144+
}
2145+
21072146
diagnosticEmitter.emitNamedFunctionArgumentClosure(
21082147
diagnosticOp->getUser()->getLoc(), rootValueAndName->first, crossing);
21092148
return true;

test/Concurrency/transfernonsendable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,7 @@ extension MyActor {
17941794
func nonSendableAllocBoxConsumingParameter(x: consuming SendableKlass) async throws {
17951795
try await withThrowingTaskGroup(of: Void.self) { group in
17961796
group.addTask { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
1797-
useValue(x) // expected-note {{closure captures reference to mutable parameter 'x' which is accessible to code in the current task}}
1797+
useValue(x) // expected-note {{closure captures reference to mutable parameter 'x' which remains modifiable by code in the current task}}
17981798
}
17991799

18001800
try await group.waitForAll()
@@ -1807,7 +1807,7 @@ func nonSendableAllocBoxConsumingVar() async throws {
18071807

18081808
try await withThrowingTaskGroup(of: Void.self) { group in
18091809
group.addTask { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
1810-
useValue(x) // expected-note {{closure captures reference to mutable var 'x' which is accessible to code in the current task}}
1810+
useValue(x) // expected-note {{closure captures reference to mutable var 'x' which remains modifiable by code in the current task}}
18111811
}
18121812

18131813
try await group.waitForAll()
@@ -1865,7 +1865,7 @@ func testFunctionIsNotEmpty(input: SendableKlass) async throws {
18651865
var result: [SendableKlass] = []
18661866
try await withThrowingTaskGroup(of: Void.self) { taskGroup in // expected-warning {{no calls to throwing functions occur within 'try' expression}}
18671867
taskGroup.addTask { // expected-warning {{passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure}}
1868-
result.append(input) // expected-note {{closure captures reference to mutable var 'result' which is accessible to code in the current task}}
1868+
result.append(input) // expected-note {{closure captures reference to mutable var 'result' which remains modifiable by code in the current task}}
18691869
}
18701870
}
18711871
}

test/Concurrency/transfernonsendable_closure_captures.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func testMutableCopyableSendableStructWithEscapingMainActorAsync() {
5050
let _ = {
5151
escapingAsyncUse { @MainActor in
5252
useValue(x) // expected-error {{sending 'x' risks causing data races}}
53-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
53+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
5454
}
5555
}
5656
}
@@ -142,7 +142,7 @@ func testMutableNoncopyableSendableStructWithEscapingMainActorAsync() {
142142
let _ = {
143143
escapingAsyncUse { @MainActor in
144144
useValue(x) // expected-error {{sending 'x' risks causing data races}}
145-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
145+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
146146
}
147147
}
148148
}
@@ -191,7 +191,7 @@ func testNoncopyableNonsendableStructWithNonescapingMainActorAsync() {
191191
let x = NoncopyableStructNonsendable()
192192
let _ = {
193193
nonescapingAsyncUse { @MainActor in
194-
useValue(x) // expected-error {{sending 'x' risks causing data races}}
194+
useValue(x) // expected-error {{sending 'x' risks causing data races}}
195195
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
196196
}
197197
}
@@ -382,7 +382,7 @@ func testCopyableSendableClassWithEscapingMainActorAsyncWeakCapture() {
382382
let _ = { [weak x] in
383383
escapingAsyncUse { @MainActor in
384384
useValue(x) // expected-error {{sending 'x' risks causing data races}}
385-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
385+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
386386
}
387387
}
388388
}
@@ -393,7 +393,7 @@ func testMutableCopyableSendableClassWithEscapingMainActorAsyncWeakCapture() {
393393
let _ = { [weak x] in
394394
escapingAsyncUse { @MainActor in
395395
useValue(x) // expected-error {{sending 'x' risks causing data races}}
396-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
396+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
397397
}
398398
}
399399
}
@@ -424,7 +424,7 @@ func testCopyableSendableClassWithNonescapingMainActorAsyncWeakCapture() {
424424
let _ = { [weak x] in
425425
nonescapingAsyncUse { @MainActor in
426426
useValue(x) // expected-error {{sending 'x' risks causing data races}}
427-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
427+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
428428
}
429429
}
430430
}
@@ -435,7 +435,7 @@ func testMutableCopyableSendableClassWithNonescapingMainActorAsyncWeakCapture()
435435
let _ = { [weak x] in
436436
nonescapingAsyncUse { @MainActor in
437437
useValue(x) // expected-error {{sending 'x' risks causing data races}}
438-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
438+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
439439
}
440440
}
441441
}
@@ -556,7 +556,7 @@ func testGenericSendableWithEscapingMainActorAsync<T : ~Copyable>(_ value: consu
556556
let _ = {
557557
escapingAsyncUse { @MainActor in
558558
useValue(x) // expected-error {{sending 'x' risks causing data races}}
559-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
559+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
560560
}
561561
}
562562
}
@@ -569,7 +569,7 @@ func testMutableGenericSendableWithEscapingMainActorAsync<T : ~Copyable>(
569569
let _ = {
570570
escapingAsyncUse { @MainActor in
571571
useValue(x) // expected-error {{sending 'x' risks causing data races}}
572-
// expected-note @-1 {{task-isolated 'x' is captured by a main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
572+
// expected-note @-1 {{main actor-isolated closure captures reference to mutable 'x' which remains modifiable by code in the current task}}
573573
}
574574
}
575575
}

0 commit comments

Comments
 (0)