Skip to content

Commit 6a53e9a

Browse files
authored
Merge pull request #73446 from gottesmm/rdar127580781
[region-isolation] Some diagnostic tweaks
2 parents bcd08c0 + 58fd432 commit 6a53e9a

31 files changed

+1201
-1092
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ NOTE(sil_referencebinding_inout_binding_here, none,
943943
//===----------------------------------------------------------------------===//
944944

945945
NOTE(regionbasedisolation_maybe_race, none,
946-
"use here could race", ())
946+
"risks concurrent access", ())
947947
ERROR(regionbasedisolation_unknown_pattern, none,
948948
"pattern that the region based isolation checker does not understand how to check. Please file a bug",
949949
())
@@ -953,10 +953,10 @@ ERROR(regionbasedisolation_unknown_pattern, none,
953953
//
954954

955955
ERROR(regionbasedisolation_transfer_yields_race_no_isolation, none,
956-
"transferring value of non-Sendable type %0; later accesses could race",
956+
"sending value of non-Sendable type %0; later accesses could race",
957957
(Type))
958958
ERROR(regionbasedisolation_transfer_yields_race_with_isolation, none,
959-
"transferring value of non-Sendable type %0 from %1 context to %2 context; later accesses could race",
959+
"sending value of non-Sendable type %0 from %1 context to %2 context; later accesses could race",
960960
(Type, ActorIsolation, ActorIsolation))
961961
ERROR(regionbasedisolation_isolated_capture_yields_race, none,
962962
"%1 closure captures value of non-Sendable type %0 from %2 context; later accesses to value could race",
@@ -965,7 +965,7 @@ ERROR(regionbasedisolation_transfer_yields_race_stronglytransferred_binding, non
965965
"value of non-Sendable type %0 accessed after being transferred; later accesses could race",
966966
(Type))
967967
ERROR(regionbasedisolation_arg_transferred, none,
968-
"%0 value of type %1 transferred to %2 context; later accesses to value could race",
968+
"sending %0 value of type %1 to %2 context; later accesses to value could race",
969969
(StringRef, Type, ActorIsolation))
970970
ERROR(regionbasedisolation_arg_passed_to_strongly_transferred_param, none,
971971
"%0 value of type %1 passed as a strongly transferred parameter; later accesses could race",
@@ -979,31 +979,38 @@ NOTE(regionbasedisolation_isolated_since_in_same_region_basename, none,
979979
//
980980

981981
ERROR(regionbasedisolation_named_transfer_yields_race, none,
982-
"transferring %0 may cause a data race",
982+
"sending %0 risks causing data races",
983983
(Identifier))
984984

985985
NOTE(regionbasedisolation_named_info_transfer_yields_race, none,
986-
"transferring %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-
"transferring %1 %0 to %2 callee could cause races between %2 and %1 uses",
990-
(Identifier, StringRef, ActorIsolation))
993+
"sending %1%0 to %2 callee risks causing data races between %2 and %3 uses",
994+
(Identifier, StringRef, ActorIsolation, StringRef))
995+
NOTE(regionbasedisolation_named_transfer_non_transferrable_callee, none,
996+
"sending %1%0 to %2 %3 %4 risks causing data races between %2 and %5 uses",
997+
(Identifier, StringRef, ActorIsolation, DescriptiveDeclKind, DeclName, StringRef))
991998
NOTE(regionbasedisolation_named_transfer_into_transferring_param, none,
992-
"%0 %1 is passed as a transferring parameter; Uses in callee may race with later %0 uses",
999+
"%0%1 is passed as a transferring parameter; Uses in callee may race with later %0uses",
9931000
(StringRef, Identifier))
9941001
NOTE(regionbasedisolation_named_notransfer_transfer_into_result, none,
995-
"%0 %1 cannot be a transferring result. %0 uses may race with caller uses",
996-
(StringRef, Identifier))
1002+
"%0%1 cannot be a transferring result. %2 uses may race with caller uses",
1003+
(StringRef, Identifier, StringRef))
9971004
NOTE(regionbasedisolation_named_stronglytransferred_binding, none,
9981005
"%0 used after being passed as a transferring parameter; Later uses could race",
9991006
(Identifier))
10001007
NOTE(regionbasedisolation_named_isolated_closure_yields_race, none,
1001-
"%0 %1 is captured by a %2 closure. %2 uses in closure may race against later %3 uses",
1008+
"%0%1 is captured by a %2 closure. %2 uses in closure may race against later %3 uses",
10021009
(StringRef, Identifier, ActorIsolation, ActorIsolation))
10031010

10041011
// Misc Error.
10051012
ERROR(regionbasedisolation_task_or_actor_isolated_transferred, none,
1006-
"task or actor isolated value cannot be transferred", ())
1013+
"task or actor isolated value cannot be sent", ())
10071014

10081015
// TODO: print the name of the nominal type
10091016
ERROR(deinit_not_visible, none,

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 124 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,50 @@ getDiagnosticBehaviorLimitForValue(SILValue value) {
8585
: DiagnosticBehavior::Ignore;
8686
}
8787

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

519+
/// If we can find a callee decl name, return that. None otherwise.
520+
std::optional<std::pair<DescriptiveDeclKind, DeclName>>
521+
getTransferringCalleeInfo() const {
522+
return getTransferringApplyCalleeInfo(transferOp->getUser());
523+
}
524+
475525
void
476526
emitNamedIsolationCrossingError(SILLocation loc, Identifier name,
477527
SILIsolationInfo namedValuesIsolationInfo,
@@ -485,13 +535,26 @@ class UseAfterTransferDiagnosticEmitter {
485535
// Then emit the note with greater context.
486536
SmallString<64> descriptiveKindStr;
487537
{
488-
llvm::raw_svector_ostream os(descriptiveKindStr);
489-
namedValuesIsolationInfo.printForDiagnostics(os);
538+
if (!namedValuesIsolationInfo.isDisconnected()) {
539+
llvm::raw_svector_ostream os(descriptiveKindStr);
540+
namedValuesIsolationInfo.printForDiagnostics(os);
541+
os << ' ';
542+
}
543+
}
544+
545+
if (auto calleeInfo = getTransferringCalleeInfo()) {
546+
diagnoseNote(
547+
loc,
548+
diag::regionbasedisolation_named_info_transfer_yields_race_callee,
549+
name, descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
550+
calleeInfo->first, calleeInfo->second,
551+
isolationCrossing.getCallerIsolation());
552+
} else {
553+
diagnoseNote(
554+
loc, diag::regionbasedisolation_named_info_transfer_yields_race, name,
555+
descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
556+
isolationCrossing.getCallerIsolation());
490557
}
491-
diagnoseNote(
492-
loc, diag::regionbasedisolation_named_info_transfer_yields_race, name,
493-
descriptiveKindStr, isolationCrossing.getCalleeIsolation(),
494-
isolationCrossing.getCallerIsolation());
495558
emitRequireInstDiagnostics();
496559
}
497560

@@ -557,8 +620,11 @@ class UseAfterTransferDiagnosticEmitter {
557620

558621
SmallString<64> descriptiveKindStr;
559622
{
560-
llvm::raw_svector_ostream os(descriptiveKindStr);
561-
namedValuesIsolationInfo.printForDiagnostics(os);
623+
if (!namedValuesIsolationInfo.isDisconnected()) {
624+
llvm::raw_svector_ostream os(descriptiveKindStr);
625+
namedValuesIsolationInfo.printForDiagnostics(os);
626+
os << ' ';
627+
}
562628
}
563629

564630
diagnoseNote(
@@ -987,6 +1053,12 @@ class TransferNonTransferrableDiagnosticEmitter {
9871053
return getDiagnosticBehaviorLimitForValue(info.transferredOperand->get());
9881054
}
9891055

1056+
/// If we can find a callee decl name, return that. None otherwise.
1057+
std::optional<std::pair<DescriptiveDeclKind, DeclName>>
1058+
getTransferringCalleeInfo() const {
1059+
return getTransferringApplyCalleeInfo(info.transferredOperand->getUser());
1060+
}
1061+
9901062
/// Return the isolation region info for \p getNonTransferrableValue().
9911063
SILIsolationInfo getIsolationRegionInfo() const {
9921064
return info.isolationRegionInfo;
@@ -1013,8 +1085,7 @@ class TransferNonTransferrableDiagnosticEmitter {
10131085
getIsolationRegionInfo().printForDiagnostics(os);
10141086
}
10151087
diagnoseError(loc, diag::regionbasedisolation_arg_transferred,
1016-
StringRef(descriptiveKindStr), type,
1017-
crossing.getCalleeIsolation())
1088+
descriptiveKindStr, type, crossing.getCalleeIsolation())
10181089
.highlight(getOperand()->getUser()->getLoc().getSourceRange())
10191090
.limitBehaviorIf(getBehaviorLimit());
10201091
}
@@ -1024,8 +1095,11 @@ class TransferNonTransferrableDiagnosticEmitter {
10241095
emitNamedOnlyError(loc, name);
10251096
SmallString<64> descriptiveKindStr;
10261097
{
1027-
llvm::raw_svector_ostream os(descriptiveKindStr);
1028-
getIsolationRegionInfo().printForDiagnostics(os);
1098+
if (!getIsolationRegionInfo().isDisconnected()) {
1099+
llvm::raw_svector_ostream os(descriptiveKindStr);
1100+
getIsolationRegionInfo().printForDiagnostics(os);
1101+
os << ' ';
1102+
}
10291103
}
10301104
diagnoseNote(loc,
10311105
diag::regionbasedisolation_named_isolated_closure_yields_race,
@@ -1059,22 +1133,42 @@ class TransferNonTransferrableDiagnosticEmitter {
10591133
ApplyIsolationCrossing isolationCrossing) {
10601134
emitNamedOnlyError(loc, name);
10611135
SmallString<64> descriptiveKindStr;
1136+
SmallString<64> descriptiveKindStrWithSpace;
10621137
{
1063-
llvm::raw_svector_ostream os(descriptiveKindStr);
1064-
getIsolationRegionInfo().printForDiagnostics(os);
1138+
if (!getIsolationRegionInfo().isDisconnected()) {
1139+
{
1140+
llvm::raw_svector_ostream os(descriptiveKindStr);
1141+
getIsolationRegionInfo().printForDiagnostics(os);
1142+
}
1143+
descriptiveKindStrWithSpace = descriptiveKindStr;
1144+
descriptiveKindStrWithSpace.push_back(' ');
1145+
}
1146+
}
1147+
if (auto calleeInfo = getTransferringCalleeInfo()) {
1148+
diagnoseNote(
1149+
loc,
1150+
diag::regionbasedisolation_named_transfer_non_transferrable_callee,
1151+
name, descriptiveKindStrWithSpace,
1152+
isolationCrossing.getCalleeIsolation(), calleeInfo->first,
1153+
calleeInfo->second, descriptiveKindStr);
1154+
} else {
1155+
diagnoseNote(loc,
1156+
diag::regionbasedisolation_named_transfer_non_transferrable,
1157+
name, descriptiveKindStrWithSpace,
1158+
isolationCrossing.getCalleeIsolation(), descriptiveKindStr);
10651159
}
1066-
diagnoseNote(
1067-
loc, diag::regionbasedisolation_named_transfer_non_transferrable, name,
1068-
descriptiveKindStr, isolationCrossing.getCalleeIsolation());
10691160
}
10701161

10711162
void emitNamedFunctionArgumentApplyStronglyTransferred(SILLocation loc,
10721163
Identifier varName) {
10731164
emitNamedOnlyError(loc, varName);
10741165
SmallString<64> descriptiveKindStr;
10751166
{
1076-
llvm::raw_svector_ostream os(descriptiveKindStr);
1077-
getIsolationRegionInfo().printForDiagnostics(os);
1167+
if (!getIsolationRegionInfo().isDisconnected()) {
1168+
llvm::raw_svector_ostream os(descriptiveKindStr);
1169+
getIsolationRegionInfo().printForDiagnostics(os);
1170+
os << ' ';
1171+
}
10781172
}
10791173
auto diag =
10801174
diag::regionbasedisolation_named_transfer_into_transferring_param;
@@ -1084,13 +1178,21 @@ class TransferNonTransferrableDiagnosticEmitter {
10841178
void emitNamedTransferringReturn(SILLocation loc, Identifier varName) {
10851179
emitNamedOnlyError(loc, varName);
10861180
SmallString<64> descriptiveKindStr;
1181+
SmallString<64> descriptiveKindStrWithSpace;
10871182
{
1088-
llvm::raw_svector_ostream os(descriptiveKindStr);
1089-
getIsolationRegionInfo().printForDiagnostics(os);
1183+
if (!getIsolationRegionInfo().isDisconnected()) {
1184+
{
1185+
llvm::raw_svector_ostream os(descriptiveKindStr);
1186+
getIsolationRegionInfo().printForDiagnostics(os);
1187+
}
1188+
descriptiveKindStrWithSpace = descriptiveKindStr;
1189+
descriptiveKindStrWithSpace.push_back(' ');
1190+
}
10901191
}
10911192
auto diag =
10921193
diag::regionbasedisolation_named_notransfer_transfer_into_result;
1093-
diagnoseNote(loc, diag, descriptiveKindStr, varName);
1194+
diagnoseNote(loc, diag, descriptiveKindStrWithSpace, varName,
1195+
descriptiveKindStr);
10941196
}
10951197

10961198
private:

test/ClangImporter/transferring.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ func funcTestTransferringResult() async {
2727
// Just to show that without the transferring param, we generate diagnostics.
2828
let x2 = NonSendableCStruct()
2929
let y2 = returnUserDefinedFromGlobalFunction(x2)
30-
await transferToMain(x2) // expected-error {{transferring 'x2' may cause a data race}}
31-
// expected-note @-1 {{transferring disconnected 'x2' to main actor-isolated callee could cause races in between callee main actor-isolated and local nonisolated uses}}
32-
useValue(y2) // expected-note {{use here could race}}
30+
await transferToMain(x2) // expected-error {{sending 'x2' risks causing data races}}
31+
// expected-note @-1 {{sending 'x2' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}}
32+
useValue(y2) // expected-note {{risks concurrent access}}
3333
}
3434

3535
func funcTestTransferringArg() async {
3636
let x = NonSendableCStruct()
37-
transferUserDefinedIntoGlobalFunction(x) // expected-error {{transferring 'x' may cause a data race}}
37+
transferUserDefinedIntoGlobalFunction(x) // expected-error {{sending 'x' risks causing data races}}
3838
// expected-note @-1 {{'x' used after being passed as a transferring parameter}}
39-
useValue(x) // expected-note {{use here could race}}
39+
useValue(x) // expected-note {{risks concurrent access}}
4040
}

test/ClangImporter/transferring_objc.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ func methodTestTransferringResult() async {
2525
func methodTestTransferringArg() async {
2626
let x = MyType()
2727
let s = NSObject()
28-
let _ = x.getResultWithTransferringArgument(s) // expected-error {{transferring 's' may cause a data race}}
28+
let _ = x.getResultWithTransferringArgument(s) // expected-error {{sending 's' risks causing data races}}
2929
// expected-note @-1 {{'s' used after being passed as a transferring parameter; Later uses could race}}
30-
useValue(s) // expected-note {{use here could race}}
30+
useValue(s) // expected-note {{risks concurrent access}}
3131
}
3232

3333
// Make sure we just ignore the swift_attr if it is applied to something like a
@@ -45,14 +45,14 @@ func funcTestTransferringResult() async {
4545
// Just to show that without the transferring param, we generate diagnostics.
4646
let x2 = NSObject()
4747
let y2 = returnNSObjectFromGlobalFunction(x2)
48-
await transferToMain(x2) // expected-error {{transferring 'x2' may cause a data race}}
49-
// expected-note @-1 {{transferring disconnected 'x2' to main actor-isolated callee could cause races in between callee main actor-isolated and local nonisolated uses}}
50-
useValue(y2) // expected-note {{use here could race}}
48+
await transferToMain(x2) // expected-error {{sending 'x2' risks causing data races}}
49+
// expected-note @-1 {{sending 'x2' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}}
50+
useValue(y2) // expected-note {{risks concurrent access}}
5151
}
5252

5353
func funcTestTransferringArg() async {
5454
let x = NSObject()
55-
transferNSObjectToGlobalFunction(x) // expected-error {{transferring 'x' may cause a data race}}
55+
transferNSObjectToGlobalFunction(x) // expected-error {{sending 'x' risks causing data races}}
5656
// expected-note @-1 {{'x' used after being passed as a transferring parameter; Later uses could race}}
57-
useValue(x) // expected-note {{use here could race}}
57+
useValue(x) // expected-note {{risks concurrent access}}
5858
}

test/Concurrency/async_task_locals_basic_warnings_bug_isolation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ actor Test {
1818
_ body: (consuming NonSendableValue, isolated (any Actor)?) -> Void) async {
1919
Self.$local.withValue(12) {
2020
// Unexpected errors here:
21-
// error: unexpected warning produced: transferring 'body' may cause a data race; this is an error in the Swift 6 language mode
21+
// error: unexpected warning produced: transferring 'body' risks causing data races; this is an error in the Swift 6 language mode
2222
// error: unexpected note produced: actor-isolated 'body' is captured by a actor-isolated closure. actor-isolated uses in closure may race against later nonisolated uses
2323
body(NonSendableValue(), isolation)
2424
}

test/Concurrency/isolated_captures.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class NotSendable {
4040
MyActor.ns = ns
4141

4242
await { @YourActor in
43-
// expected-region-isolation-warning @+3 {{transferring 'ns' may cause a data race}}
43+
// expected-region-isolation-warning @+3 {{sending 'ns' risks causing data races}}
4444
// expected-region-isolation-note @+2 {{global actor 'MyActor'-isolated 'ns' is captured by a global actor 'YourActor'-isolated closure. global actor 'YourActor'-isolated uses in closure may race against later global actor 'MyActor'-isolated uses}}
4545
// expected-complete-warning@+1 {{capture of 'ns' with non-sendable type 'NotSendable' in an isolated closure; this is an error in the Swift 6 language mode}}
4646
YourActor.ns = ns
@@ -62,7 +62,7 @@ class NotSendable {
6262
ns.stash()
6363

6464
await { @YourActor in
65-
// expected-region-isolation-warning @+3 {{transferring 'ns' may cause a data race}}
65+
// expected-region-isolation-warning @+3 {{sending 'ns' risks causing data races}}
6666
// expected-region-isolation-note @+2 {{global actor 'MyActor'-isolated 'ns' is captured by a global actor 'YourActor'-isolated closure. global actor 'YourActor'-isolated uses in closure may race against later global actor 'MyActor'-isolated uses}}
6767
// expected-complete-warning@+1 {{capture of 'ns' with non-sendable type 'NotSendable' in an isolated closure; this is an error in the Swift 6 language mode}}
6868
YourActor.ns = ns
@@ -83,7 +83,7 @@ class NotSendable {
8383
let ns = NotSendable()
8484

8585
await { @YourActor in
86-
// expected-region-isolation-warning @+3 {{transferring 'ns' may cause a data race}}
86+
// expected-region-isolation-warning @+3 {{sending 'ns' risks causing data races}}
8787
// expected-region-isolation-note @+2 {{global actor 'MyActor'-isolated 'ns' is captured by a global actor 'YourActor'-isolated closure. global actor 'YourActor'-isolated uses in closure may race against later global actor 'MyActor'-isolated uses}}
8888
// expected-complete-warning@+1 {{capture of 'ns' with non-sendable type 'NotSendable' in an isolated closure; this is an error in the Swift 6 language mode}}
8989
YourActor.ns = ns

0 commit comments

Comments
 (0)