Skip to content

Commit d77dede

Browse files
committed
[region-isolation] Change WARNINGS to be ERRORs that are limited as warnings until swift 6.
I added some small infrastructure so that the default way one creates diagnostics sets this automagically so mistakes cannot result. rdar://121755281
1 parent 5008b5c commit d77dede

File tree

3 files changed

+136
-66
lines changed

3 files changed

+136
-66
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -890,26 +890,26 @@ NOTE(sil_referencebinding_inout_binding_here, none,
890890

891891
// Warnings arising from the flow-sensitive checking of Sendability of
892892
// non-Sendable values
893-
WARNING(regionbasedisolation_selforargtransferred, none,
894-
"call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller", ())
895-
WARNING(regionbasedisolation_transfer_yields_race_no_isolation, none,
896-
"transferring value of non-Sendable type %0; later accesses could race",
897-
(Type))
898-
WARNING(regionbasedisolation_transfer_yields_race_with_isolation, none,
899-
"transferring value of non-Sendable type %0 from %1 context to %2 context; later accesses could race",
900-
(Type, ActorIsolation, ActorIsolation))
901-
WARNING(regionbasedisolation_isolated_capture_yields_race, none,
902-
"%1 closure captures value of non-Sendable type %0 from %2 context; later accesses to value could race",
903-
(Type, ActorIsolation, ActorIsolation))
904-
WARNING(regionbasedisolation_transfer_yields_race_transferring_parameter, none,
905-
"transferring value of non-Sendable type %0 into transferring parameter; later accesses could race",
906-
(Type))
907-
WARNING(regionbasedisolation_transfer_yields_race_stronglytransferred_binding, none,
908-
"binding of non-Sendable type %0 accessed after being transferred; later accesses could race",
909-
(Type))
910-
WARNING(regionbasedisolation_arg_transferred, none,
911-
"task isolated value of type %0 transferred to %1 context; later accesses to value could race",
912-
(Type, ActorIsolation))
893+
ERROR(regionbasedisolation_selforargtransferred, none,
894+
"call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller", ())
895+
ERROR(regionbasedisolation_transfer_yields_race_no_isolation, none,
896+
"transferring value of non-Sendable type %0; later accesses could race",
897+
(Type))
898+
ERROR(regionbasedisolation_transfer_yields_race_with_isolation, none,
899+
"transferring value of non-Sendable type %0 from %1 context to %2 context; later accesses could race",
900+
(Type, ActorIsolation, ActorIsolation))
901+
ERROR(regionbasedisolation_isolated_capture_yields_race, none,
902+
"%1 closure captures value of non-Sendable type %0 from %2 context; later accesses to value could race",
903+
(Type, ActorIsolation, ActorIsolation))
904+
ERROR(regionbasedisolation_transfer_yields_race_transferring_parameter, none,
905+
"transferring value of non-Sendable type %0 into transferring parameter; later accesses could race",
906+
(Type))
907+
ERROR(regionbasedisolation_transfer_yields_race_stronglytransferred_binding, none,
908+
"binding of non-Sendable type %0 accessed after being transferred; later accesses could race",
909+
(Type))
910+
ERROR(regionbasedisolation_arg_transferred, none,
911+
"task isolated value of type %0 transferred to %1 context; later accesses to value could race",
912+
(Type, ActorIsolation))
913913
NOTE(regionbasedisolation_maybe_race, none,
914914
"access here could race", ())
915915
NOTE(regionbasedisolation_isolated_since_in_same_region_basename, none,

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 86 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -56,40 +56,78 @@ using Region = PartitionPrimitives::Region;
5656
//===----------------------------------------------------------------------===//
5757

5858
template <typename... T, typename... U>
59-
static InFlightDiagnostic diagnose(ASTContext &context, SourceLoc loc,
60-
Diag<T...> diag, U &&...args) {
59+
static InFlightDiagnostic diagnoseError(ASTContext &context, SourceLoc loc,
60+
Diag<T...> diag, U &&...args) {
61+
return std::move(context.Diags.diagnose(loc, diag, std::forward<U>(args)...)
62+
.warnUntilSwiftVersion(6));
63+
}
64+
65+
template <typename... T, typename... U>
66+
static InFlightDiagnostic diagnoseError(ASTContext &context, SILLocation loc,
67+
Diag<T...> diag, U &&...args) {
68+
return ::diagnoseError(context, loc.getSourceLoc(), diag,
69+
std::forward<U>(args)...);
70+
}
71+
72+
template <typename... T, typename... U>
73+
static InFlightDiagnostic diagnoseError(const PartitionOp &op, Diag<T...> diag,
74+
U &&...args) {
75+
return ::diagnoseError(op.getSourceInst()->getFunction()->getASTContext(),
76+
op.getSourceLoc().getSourceLoc(), diag,
77+
std::forward<U>(args)...);
78+
}
79+
80+
template <typename... T, typename... U>
81+
static InFlightDiagnostic diagnoseError(const Operand *op, Diag<T...> diag,
82+
U &&...args) {
83+
return ::diagnoseError(op->getUser()->getFunction()->getASTContext(),
84+
op->getUser()->getLoc().getSourceLoc(), diag,
85+
std::forward<U>(args)...);
86+
}
87+
88+
template <typename... T, typename... U>
89+
static InFlightDiagnostic diagnoseError(const SILInstruction *inst,
90+
Diag<T...> diag, U &&...args) {
91+
return ::diagnoseError(inst->getFunction()->getASTContext(),
92+
inst->getLoc().getSourceLoc(), diag,
93+
std::forward<U>(args)...);
94+
}
95+
96+
template <typename... T, typename... U>
97+
static InFlightDiagnostic diagnoseNote(ASTContext &context, SourceLoc loc,
98+
Diag<T...> diag, U &&...args) {
6199
return context.Diags.diagnose(loc, diag, std::forward<U>(args)...);
62100
}
63101

64102
template <typename... T, typename... U>
65-
static InFlightDiagnostic diagnose(ASTContext &context, SILLocation loc,
66-
Diag<T...> diag, U &&...args) {
67-
return ::diagnose(context, loc.getSourceLoc(), diag,
68-
std::forward<U>(args)...);
103+
static InFlightDiagnostic diagnoseNote(ASTContext &context, SILLocation loc,
104+
Diag<T...> diag, U &&...args) {
105+
return ::diagnoseNote(context, loc.getSourceLoc(), diag,
106+
std::forward<U>(args)...);
69107
}
70108

71109
template <typename... T, typename... U>
72-
static InFlightDiagnostic diagnose(const PartitionOp &op, Diag<T...> diag,
73-
U &&...args) {
74-
return ::diagnose(op.getSourceInst()->getFunction()->getASTContext(),
75-
op.getSourceLoc().getSourceLoc(), diag,
76-
std::forward<U>(args)...);
110+
static InFlightDiagnostic diagnoseNote(const PartitionOp &op, Diag<T...> diag,
111+
U &&...args) {
112+
return ::diagnoseNote(op.getSourceInst()->getFunction()->getASTContext(),
113+
op.getSourceLoc().getSourceLoc(), diag,
114+
std::forward<U>(args)...);
77115
}
78116

79117
template <typename... T, typename... U>
80-
static InFlightDiagnostic diagnose(const Operand *op, Diag<T...> diag,
81-
U &&...args) {
82-
return ::diagnose(op->getUser()->getFunction()->getASTContext(),
83-
op->getUser()->getLoc().getSourceLoc(), diag,
84-
std::forward<U>(args)...);
118+
static InFlightDiagnostic diagnoseNote(const Operand *op, Diag<T...> diag,
119+
U &&...args) {
120+
return ::diagnoseNote(op->getUser()->getFunction()->getASTContext(),
121+
op->getUser()->getLoc().getSourceLoc(), diag,
122+
std::forward<U>(args)...);
85123
}
86124

87125
template <typename... T, typename... U>
88-
static InFlightDiagnostic diagnose(const SILInstruction *inst, Diag<T...> diag,
89-
U &&...args) {
90-
return ::diagnose(inst->getFunction()->getASTContext(),
91-
inst->getLoc().getSourceLoc(), diag,
92-
std::forward<U>(args)...);
126+
static InFlightDiagnostic diagnoseNote(const SILInstruction *inst,
127+
Diag<T...> diag, U &&...args) {
128+
return ::diagnoseNote(inst->getFunction()->getASTContext(),
129+
inst->getLoc().getSourceLoc(), diag,
130+
std::forward<U>(args)...);
93131
}
94132

95133
//===----------------------------------------------------------------------===//
@@ -944,7 +982,7 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
944982
// editor UIs providing a more actionable error message.
945983
auto applyUses = diagnosticInferrer.getApplyUses();
946984
if (applyUses.empty()) {
947-
diagnose(transferOp, diag::regionbasedisolation_unknown_pattern);
985+
diagnoseError(transferOp, diag::regionbasedisolation_unknown_pattern);
948986
continue;
949987
}
950988

@@ -956,29 +994,31 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
956994
llvm_unreachable("Should never see this!");
957995
case UseDiagnosticInfoKind::IsolationCrossing: {
958996
auto isolation = info.diagInfo.getIsolationCrossing();
959-
diagnose(astContext, info.loc,
960-
diag::regionbasedisolation_transfer_yields_race_with_isolation,
961-
info.inferredType, isolation.getCallerIsolation(),
962-
isolation.getCalleeIsolation())
997+
diagnoseError(
998+
astContext, info.loc,
999+
diag::regionbasedisolation_transfer_yields_race_with_isolation,
1000+
info.inferredType, isolation.getCallerIsolation(),
1001+
isolation.getCalleeIsolation())
9631002
.highlight(info.loc.getSourceRange());
9641003
break;
9651004
}
9661005
case UseDiagnosticInfoKind::RaceWithoutKnownIsolationCrossing:
967-
diagnose(astContext, info.loc,
968-
diag::regionbasedisolation_transfer_yields_race_no_isolation,
969-
info.inferredType)
1006+
diagnoseError(
1007+
astContext, info.loc,
1008+
diag::regionbasedisolation_transfer_yields_race_no_isolation,
1009+
info.inferredType)
9701010
.highlight(info.loc.getSourceRange());
9711011
break;
9721012
case UseDiagnosticInfoKind::UseOfStronglyTransferredValue:
973-
diagnose(
1013+
diagnoseError(
9741014
astContext, info.loc,
9751015
diag::
9761016
regionbasedisolation_transfer_yields_race_stronglytransferred_binding,
9771017
info.inferredType)
9781018
.highlight(info.loc.getSourceRange());
9791019
break;
9801020
case UseDiagnosticInfoKind::AssignmentIntoTransferringParameter:
981-
diagnose(
1021+
diagnoseError(
9821022
astContext, info.loc,
9831023
diag::
9841024
regionbasedisolation_transfer_yields_race_transferring_parameter,
@@ -987,10 +1027,10 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
9871027
break;
9881028
case UseDiagnosticInfoKind::IsolationCrossingDueToCapture:
9891029
auto isolation = info.diagInfo.getIsolationCrossing();
990-
diagnose(astContext, info.loc,
991-
diag::regionbasedisolation_isolated_capture_yields_race,
992-
info.inferredType, isolation.getCalleeIsolation(),
993-
isolation.getCallerIsolation())
1030+
diagnoseError(astContext, info.loc,
1031+
diag::regionbasedisolation_isolated_capture_yields_race,
1032+
info.inferredType, isolation.getCalleeIsolation(),
1033+
isolation.getCallerIsolation())
9941034
.highlight(info.loc.getSourceRange());
9951035
break;
9961036
}
@@ -1011,7 +1051,7 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
10111051
if (!liveness.finalRequires.contains(require))
10121052
continue;
10131053

1014-
diagnose(require, diag::regionbasedisolation_maybe_race)
1054+
diagnoseNote(require, diag::regionbasedisolation_maybe_race)
10151055
.highlight(require->getLoc().getSourceRange());
10161056
didEmitRequire = true;
10171057
}
@@ -1041,13 +1081,13 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
10411081
case UseDiagnosticInfoKind::Invalid:
10421082
llvm_unreachable("Should never see this");
10431083
case UseDiagnosticInfoKind::MiscUse:
1044-
diagnose(astContext, loc,
1045-
diag::regionbasedisolation_selforargtransferred);
1084+
diagnoseError(astContext, loc,
1085+
diag::regionbasedisolation_selforargtransferred);
10461086
break;
10471087
case UseDiagnosticInfoKind::FunctionArgumentApply: {
1048-
diagnose(astContext, loc, diag::regionbasedisolation_arg_transferred,
1049-
op->get()->getType().getASTType(),
1050-
diagnosticInfo.transferredIsolation.value())
1088+
diagnoseError(astContext, loc, diag::regionbasedisolation_arg_transferred,
1089+
op->get()->getType().getASTType(),
1090+
diagnosticInfo.transferredIsolation.value())
10511091
.highlight(op->getUser()->getLoc().getSourceRange());
10521092
// Only emit the note if our value is different from the function
10531093
// argument.
@@ -1057,16 +1097,16 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
10571097
if (rep.maybeGetValue() == info.nonTransferrableValue)
10581098
continue;
10591099
auto *fArg = cast<SILFunctionArgument>(info.nonTransferrableValue);
1060-
diagnose(
1100+
diagnoseNote(
10611101
astContext, fArg->getDecl()->getLoc(),
10621102
diag::regionbasedisolation_isolated_since_in_same_region_basename,
10631103
"task isolated", fArg->getDecl()->getBaseName());
10641104
break;
10651105
}
10661106
case UseDiagnosticInfoKind::FunctionArgumentClosure: {
1067-
diagnose(astContext, loc, diag::regionbasedisolation_arg_transferred,
1068-
op->get()->getType().getASTType(),
1069-
diagnosticInfo.transferredIsolation.value())
1107+
diagnoseError(astContext, loc, diag::regionbasedisolation_arg_transferred,
1108+
op->get()->getType().getASTType(),
1109+
diagnosticInfo.transferredIsolation.value())
10701110
.highlight(op->getUser()->getLoc().getSourceRange());
10711111
// Only emit the note if our value is different from the function
10721112
// argument.
@@ -1076,7 +1116,7 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
10761116
if (rep.maybeGetValue() == info.nonTransferrableValue)
10771117
continue;
10781118
auto *fArg = cast<SILFunctionArgument>(info.nonTransferrableValue);
1079-
diagnose(
1119+
diagnoseNote(
10801120
astContext, fArg->getDecl()->getLoc(),
10811121
diag::regionbasedisolation_isolated_since_in_same_region_basename,
10821122
"task isolated", fArg->getDecl()->getBaseName());
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-swift-frontend -emit-sil -strict-concurrency=complete -enable-experimental-feature RegionBasedIsolation -disable-availability-checking -verify %s -o /dev/null -swift-version 6 -enable-experimental-feature TransferringArgsAndResults
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: asserts
5+
6+
// This test makes sure that all of our warnings are errors in swift6 mode.
7+
8+
////////////////////////
9+
// MARK: Declarations //
10+
////////////////////////
11+
12+
class NonSendableType {}
13+
14+
@MainActor func transferToMain<T>(_ t: T) async {}
15+
func useValue<T>(_ t: T) {}
16+
func transferValue<T>(_ t: transferring T) {}
17+
18+
/////////////////
19+
// MARK: Tests //
20+
/////////////////
21+
22+
func testIsolationError() async {
23+
let x = NonSendableType()
24+
await transferToMain(x) // expected-error {{transferring value of non-Sendable type 'NonSendableType' from nonisolated context to main actor-isolated context; later accesses could race}}
25+
useValue(x) // expected-note {{access here could race}}
26+
}
27+
28+
func testArgumentError(_ x: NonSendableType) async { // expected-note {{value is task isolated since it is in the same region as 'x'}}
29+
await transferToMain(x) // expected-error {{task isolated value of type 'NonSendableType' transferred to main actor-isolated context; later accesses to value could race}}
30+
}

0 commit comments

Comments
 (0)