Skip to content

Commit 0b76110

Browse files
committed
[region-isolation] If we can infer the callee's name, use that instead of just saying 'callee'.
I also wordsmithed the error message to use the term 'risk' instead of less negative terms.
1 parent 699692b commit 0b76110

18 files changed

+344
-261
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,11 +983,18 @@ ERROR(regionbasedisolation_named_transfer_yields_race, none,
983983
(Identifier))
984984

985985
NOTE(regionbasedisolation_named_info_transfer_yields_race, none,
986-
"sending %1 %0 to %2 callee could cause races in between callee %2 and local %3 uses",
986+
"sending %1 %0 to %2 callee risks causing data races between %2 and local %3 uses",
987987
(Identifier, StringRef, ActorIsolation, ActorIsolation))
988+
NOTE(regionbasedisolation_named_info_transfer_yields_race_callee, none,
989+
"sending %1 %0 to %2 %3 %4 risks causing data races between %2 and local %5 uses",
990+
(Identifier, StringRef, ActorIsolation, DescriptiveDeclKind, DeclName, ActorIsolation))
991+
988992
NOTE(regionbasedisolation_named_transfer_non_transferrable, none,
989-
"sending %1 %0 to %2 callee could cause races between %2 and %1 uses",
993+
"sending %1 %0 to %2 callee risks causing data races between %2 and %1 uses",
990994
(Identifier, StringRef, ActorIsolation))
995+
NOTE(regionbasedisolation_named_transfer_non_transferrable_callee, none,
996+
"sending %1 %0 to %2 %3 %4 risks causing data races between %2 and %1 uses",
997+
(Identifier, StringRef, ActorIsolation, DescriptiveDeclKind, DeclName))
991998
NOTE(regionbasedisolation_named_transfer_into_transferring_param, none,
992999
"%0 %1 is passed as a transferring parameter; Uses in callee may race with later %0 uses",
9931000
(StringRef, Identifier))

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#include "llvm/ADT/DenseMap.h"
4242
#include "llvm/Support/Debug.h"
4343

44+
#pragma clang optimize off
45+
4446
using namespace swift;
4547
using namespace swift::PartitionPrimitives;
4648
using namespace swift::PatternMatch;
@@ -85,6 +87,50 @@ getDiagnosticBehaviorLimitForValue(SILValue value) {
8587
: DiagnosticBehavior::Ignore;
8688
}
8789

90+
static std::optional<SILDeclRef> getDeclRefForCallee(SILInstruction *inst) {
91+
auto fas = FullApplySite::isa(inst);
92+
if (!fas)
93+
return {};
94+
95+
SILValue calleeOrigin = fas.getCalleeOrigin();
96+
97+
while (true) {
98+
// Intentionally don't lookup through dynamic_function_ref and
99+
// previous_dynamic_function_ref as the target of those functions is not
100+
// statically known.
101+
if (auto *fri = dyn_cast<FunctionRefInst>(calleeOrigin)) {
102+
if (auto *callee = fri->getReferencedFunctionOrNull()) {
103+
if (auto declRef = callee->getDeclRef())
104+
return declRef;
105+
}
106+
}
107+
108+
if (auto *mi = dyn_cast<MethodInst>(calleeOrigin)) {
109+
return mi->getMember();
110+
}
111+
112+
if (auto *pai = dyn_cast<PartialApplyInst>(calleeOrigin)) {
113+
calleeOrigin = pai->getCalleeOrigin();
114+
continue;
115+
}
116+
117+
return {};
118+
}
119+
}
120+
121+
static std::optional<std::pair<DescriptiveDeclKind, DeclName>>
122+
getTransferringApplyCalleeInfo(SILInstruction *inst) {
123+
auto declRef = getDeclRefForCallee(inst);
124+
if (!declRef)
125+
return {};
126+
127+
auto *decl = declRef->getDecl();
128+
if (!decl->hasName())
129+
return {};
130+
131+
return {{decl->getDescriptiveKind(), decl->getName()}};
132+
}
133+
88134
static Expr *inferArgumentExprFromApplyExpr(ApplyExpr *sourceApply,
89135
FullApplySite fai,
90136
const Operand *op) {
@@ -472,6 +518,12 @@ class UseAfterTransferDiagnosticEmitter {
472518
return getDiagnosticBehaviorLimitForValue(transferOp->get());
473519
}
474520

521+
/// If we can find a callee decl name, return that. None otherwise.
522+
std::optional<std::pair<DescriptiveDeclKind, DeclName>>
523+
getTransferringCalleeInfo() const {
524+
return getTransferringApplyCalleeInfo(transferOp->getUser());
525+
}
526+
475527
void
476528
emitNamedIsolationCrossingError(SILLocation loc, Identifier name,
477529
SILIsolationInfo namedValuesIsolationInfo,
@@ -488,10 +540,20 @@ class UseAfterTransferDiagnosticEmitter {
488540
llvm::raw_svector_ostream os(descriptiveKindStr);
489541
namedValuesIsolationInfo.printForDiagnostics(os);
490542
}
491-
diagnoseNote(
492-
loc, diag::regionbasedisolation_named_info_transfer_yields_race, name,
493-
descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
494-
isolationCrossing.getCallerIsolation());
543+
544+
if (auto calleeInfo = getTransferringCalleeInfo()) {
545+
diagnoseNote(
546+
loc,
547+
diag::regionbasedisolation_named_info_transfer_yields_race_callee,
548+
name, descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
549+
calleeInfo->first, calleeInfo->second,
550+
isolationCrossing.getCallerIsolation());
551+
} else {
552+
diagnoseNote(
553+
loc, diag::regionbasedisolation_named_info_transfer_yields_race, name,
554+
descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
555+
isolationCrossing.getCallerIsolation());
556+
}
495557
emitRequireInstDiagnostics();
496558
}
497559

@@ -987,6 +1049,12 @@ class TransferNonTransferrableDiagnosticEmitter {
9871049
return getDiagnosticBehaviorLimitForValue(info.transferredOperand->get());
9881050
}
9891051

1052+
/// If we can find a callee decl name, return that. None otherwise.
1053+
std::optional<std::pair<DescriptiveDeclKind, DeclName>>
1054+
getTransferringCalleeInfo() const {
1055+
return getTransferringApplyCalleeInfo(info.transferredOperand->getUser());
1056+
}
1057+
9901058
/// Return the isolation region info for \p getNonTransferrableValue().
9911059
SILIsolationInfo getIsolationRegionInfo() const {
9921060
return info.isolationRegionInfo;
@@ -1063,9 +1131,17 @@ class TransferNonTransferrableDiagnosticEmitter {
10631131
llvm::raw_svector_ostream os(descriptiveKindStr);
10641132
getIsolationRegionInfo().printForDiagnostics(os);
10651133
}
1066-
diagnoseNote(
1067-
loc, diag::regionbasedisolation_named_transfer_non_transferrable, name,
1068-
descriptiveKindStr, isolationCrossing.getCalleeIsolation());
1134+
if (auto calleeInfo = getTransferringCalleeInfo()) {
1135+
diagnoseNote(
1136+
loc,
1137+
diag::regionbasedisolation_named_transfer_non_transferrable_callee,
1138+
name, descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
1139+
calleeInfo->first, calleeInfo->second);
1140+
} else {
1141+
diagnoseNote(
1142+
loc, diag::regionbasedisolation_named_transfer_non_transferrable,
1143+
name, descriptiveKindStr, isolationCrossing.getCalleeIsolation());
1144+
}
10691145
}
10701146

10711147
void emitNamedFunctionArgumentApplyStronglyTransferred(SILLocation loc,

test/Concurrency/sendable_checking.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public actor MyActor: MyProto {
9797
func g(ns1: NS1) async {
9898
await nonisolatedAsyncFunc1(ns1) // expected-targeted-and-complete-warning{{passing argument of non-sendable type 'NS1' outside of actor-isolated context may introduce data races}}
9999
// expected-tns-warning @-1 {{sending 'ns1' may cause a data race}}
100-
// expected-tns-note @-2 {{sending actor-isolated 'ns1' to nonisolated callee could cause races between nonisolated and actor-isolated uses}}
100+
// expected-tns-note @-2 {{sending actor-isolated 'ns1' to nonisolated global function 'nonisolatedAsyncFunc1' risks causing data races between nonisolated and actor-isolated uses}}
101101
_ = await nonisolatedAsyncFunc2() // expected-warning{{non-sendable type 'NS1' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary}}
102102
}
103103
}
@@ -254,12 +254,12 @@ final class NonSendable {
254254
await update()
255255
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
256256
// expected-tns-warning @-2 {{sending 'self' may cause a data race}}
257-
// expected-tns-note @-3 {{sending task-isolated 'self' to main actor-isolated callee could cause races between main actor-isolated and task-isolated uses}}
257+
// expected-tns-note @-3 {{sending task-isolated 'self' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and task-isolated uses}}
258258

259259
await self.update()
260260
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
261261
// expected-tns-warning @-2 {{sending 'self' may cause a data race}}
262-
// expected-tns-note @-3 {{sending task-isolated 'self' to main actor-isolated callee could cause races between main actor-isolated and task-isolated uses}}
262+
// expected-tns-note @-3 {{sending task-isolated 'self' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and task-isolated uses}}
263263

264264
_ = await x
265265
// expected-warning@-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to main actor-isolated property 'x' cannot cross actor boundary}}
@@ -278,7 +278,7 @@ func testNonSendableBaseArg() async {
278278
await t.update()
279279
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
280280
// expected-tns-warning @-2 {{sending 't' may cause a data race}}
281-
// expected-tns-note @-3 {{sending disconnected 't' to main actor-isolated callee could cause races in between callee main actor-isolated and local nonisolated uses}}
281+
// expected-tns-note @-3 {{sending disconnected 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}}
282282

283283
_ = await t.x
284284
// expected-warning @-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to main actor-isolated property 'x' cannot cross actor boundary}}
@@ -298,13 +298,13 @@ func callNonisolatedAsyncClosure(
298298
await g(ns)
299299
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' outside of main actor-isolated context may introduce data races}}
300300
// expected-tns-warning @-2 {{sending 'ns' may cause a data race}}
301-
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee could cause races between nonisolated and main actor-isolated uses}}
301+
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
302302

303303
let f: (NonSendable) async -> () = globalSendable // okay
304304
await f(ns)
305305
// expected-targeted-and-complete-warning@-1 {{passing argument of non-sendable type 'NonSendable' outside of main actor-isolated context may introduce data races}}
306306
// expected-tns-warning @-2 {{sending 'ns' may cause a data race}}
307-
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee could cause races between nonisolated and main actor-isolated uses}}
307+
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
308308
}
309309

310310
@available(SwiftStdlib 5.1, *)

0 commit comments

Comments
 (0)