Skip to content

Commit 7d07fb5

Browse files
committed
[region-isolation] Add a named variant of the transfer via closure capture diagnostic.
Just converting another diagnostic to its final named form.
1 parent 5580bb4 commit 7d07fb5

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,9 @@ NOTE(regionbasedisolation_named_notransfer_transfer_into_result, none,
984984
NOTE(regionbasedisolation_named_stronglytransferred_binding, none,
985985
"%0 used after being passed as a transferring parameter; Later uses could race",
986986
(Identifier))
987+
NOTE(regionbasedisolation_named_isolated_closure_yields_race, none,
988+
"%0 %1 is captured by %2 closure. %2 uses in closure may race against later %3 uses",
989+
(StringRef, Identifier, ActorIsolation, ActorIsolation))
987990

988991
// Misc Error.
989992
ERROR(regionbasedisolation_task_or_actor_isolated_transferred, none,

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -491,9 +491,10 @@ class UseAfterTransferDiagnosticEmitter {
491491
emitUnknownPatternError();
492492
}
493493

494-
void emitNamedIsolationCrossingError(SILLocation loc, Identifier name,
495-
SILIsolationInfo namesIsolationInfo,
496-
ApplyIsolationCrossing isolationCrossing) {
494+
void
495+
emitNamedIsolationCrossingError(SILLocation loc, Identifier name,
496+
SILIsolationInfo namedValuesIsolationInfo,
497+
ApplyIsolationCrossing isolationCrossing) {
497498
// Emit the short error.
498499
diagnoseError(loc, diag::regionbasedisolation_named_transfer_yields_race,
499500
name)
@@ -503,7 +504,7 @@ class UseAfterTransferDiagnosticEmitter {
503504
SmallString<64> descriptiveKindStr;
504505
{
505506
llvm::raw_svector_ostream os(descriptiveKindStr);
506-
namesIsolationInfo.printForDiagnostics(os);
507+
namedValuesIsolationInfo.printForDiagnostics(os);
507508
}
508509
diagnoseNote(
509510
loc, diag::regionbasedisolation_named_info_transfer_yields_race, name,
@@ -558,6 +559,29 @@ class UseAfterTransferDiagnosticEmitter {
558559
emitRequireInstDiagnostics();
559560
}
560561

562+
void emitNamedIsolationCrossingDueToCapture(
563+
SILLocation loc, Identifier name,
564+
SILIsolationInfo namedValuesIsolationInfo,
565+
ApplyIsolationCrossing isolationCrossing) {
566+
// Emit the short error.
567+
diagnoseError(loc, diag::regionbasedisolation_named_transfer_yields_race,
568+
name)
569+
.highlight(loc.getSourceRange());
570+
571+
SmallString<64> descriptiveKindStr;
572+
{
573+
llvm::raw_svector_ostream os(descriptiveKindStr);
574+
namedValuesIsolationInfo.printForDiagnostics(os);
575+
}
576+
577+
diagnoseNote(
578+
loc, diag::regionbasedisolation_named_isolated_closure_yields_race,
579+
descriptiveKindStr, name, isolationCrossing.getCalleeIsolation(),
580+
isolationCrossing.getCallerIsolation())
581+
.highlight(loc.getSourceRange());
582+
emitRequireInstDiagnostics();
583+
}
584+
561585
void emitTypedIsolationCrossingDueToCapture(
562586
SILLocation loc, Type inferredType,
563587
ApplyIsolationCrossing isolationCrossing) {
@@ -687,16 +711,25 @@ bool UseAfterTransferDiagnosticInferrer::initForIsolatedPartialApply(
687711
return false;
688712

689713
unsigned opIndex = ApplySite(op->getUser()).getAppliedArgIndex(*op);
714+
bool emittedDiagnostic = false;
690715
for (auto &p : foundCapturedIsolationCrossing) {
691-
if (std::get<1>(p) == opIndex) {
692-
diagnosticEmitter.emitTypedIsolationCrossingDueToCapture(
693-
RegularLocation(std::get<0>(p).getLoc()), baseInferredType,
694-
std::get<2>(p));
695-
return true;
716+
if (std::get<1>(p) != opIndex)
717+
continue;
718+
emittedDiagnostic = true;
719+
720+
if (auto rootValueAndName = inferNameAndRootFromValue(transferOp->get())) {
721+
diagnosticEmitter.emitNamedIsolationCrossingDueToCapture(
722+
RegularLocation(std::get<0>(p).getLoc()), rootValueAndName->first,
723+
transferOp->getIsolationInfo(), std::get<2>(p));
724+
continue;
696725
}
726+
727+
diagnosticEmitter.emitTypedIsolationCrossingDueToCapture(
728+
RegularLocation(std::get<0>(p).getLoc()), baseInferredType,
729+
std::get<2>(p));
697730
}
698731

699-
return false;
732+
return emittedDiagnostic;
700733
}
701734

702735
void UseAfterTransferDiagnosticInferrer::initForApply(Operand *op,

test/Concurrency/transfernonsendable_isolationcrossing_partialapply.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ actor ProtectsNonSendable {
6565

6666
// This is not safe since we use l later.
6767
self.assumeIsolated { isolatedSelf in
68-
isolatedSelf.ns = l // expected-warning {{actor-isolated closure captures value of non-Sendable type 'NonSendableKlass' from nonisolated context; later accesses to value could race}}
68+
isolatedSelf.ns = l // expected-warning {{transferring 'l' may cause a race}}
69+
// expected-note @-1 {{disconnected 'l' is captured by actor-isolated closure. actor-isolated uses in closure may race against later nonisolated uses}}
6970
}
7071

7172
useValue(l) // expected-note {{use here could race}}
@@ -82,7 +83,8 @@ func normalFunc_testLocal_1() {
8283
func normalFunc_testLocal_2() {
8384
let x = NonSendableKlass()
8485
let _ = { @MainActor in
85-
useValue(x) // expected-warning {{main actor-isolated closure captures value of non-Sendable type 'NonSendableKlass' from nonisolated context; later accesses to value could race}}
86+
useValue(x) // expected-warning {{transferring 'x' may cause a race}}
87+
// expected-note @-1 {{disconnected 'x' is captured by main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
8688
}
8789
useValue(x) // expected-note {{use here could race}}
8890
}

test/Concurrency/transfernonsendable_warning_until_swift6.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ func testAssigningParameterIntoTransferringParameter(_ x: transferring NonSendab
4949
func testIsolationCrossingDueToCapture() async {
5050
let x = NonSendableType()
5151
let _ = { @MainActor in
52-
print(x) // expected-error {{main actor-isolated closure captures value of non-Sendable type 'NonSendableType' from nonisolated context; later accesses to value could race}}
52+
print(x) // expected-error {{transferring 'x' may cause a race}}
53+
// expected-note @-1 {{disconnected 'x' is captured by main actor-isolated closure. main actor-isolated uses in closure may race against later nonisolated uses}}
5354
}
5455
useValue(x) // expected-note {{use here could race}}
5556
}

0 commit comments

Comments
 (0)