Skip to content

Commit dfea802

Browse files
committed
[Concurrency] Delete sendable checking subsumed by region isolation.
Sema's sendable checking is subsumed by the region isolation SIL pass. Now that region isolation is always enabled under complete concurrency checking, the code can be deleted from the actor isolation checker. Note that this removes these diagnostics from targeted concurrency checking. I think it's better to remove these diagnostics from targeted checking because in many cases, they're false positive data-race reports that the programmer ultimately won't have to address. If we want these diagnostics in targeted checking, we should do it via region isolation.
1 parent 95cff2a commit dfea802

File tree

5 files changed

+38
-169
lines changed

5 files changed

+38
-169
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5520,9 +5520,6 @@ ERROR(non_sendable_isolated_capture,none,
55205520
"capture of %1 with non-sendable type %0 in an isolated "
55215521
"%select{local function|closure}2",
55225522
(Type, DeclName, bool))
5523-
ERROR(implicit_async_let_non_sendable_capture,none,
5524-
"capture of %1 with non-sendable type %0 in 'async let' binding",
5525-
(Type, DeclName))
55265523
ERROR(self_capture_deinit_task,none,
55275524
"capture of 'self' in a closure that outlives deinit",
55285525
())
@@ -5642,10 +5639,6 @@ ERROR(non_sendable_param_type,none,
56425639
"in parameter of superclass method overridden by %3 %kind2|"
56435640
"in parameter of %3 '@objc' %kind2}1 cannot cross actor boundary",
56445641
(Type, unsigned, const ValueDecl *, ActorIsolation))
5645-
ERROR(non_sendable_call_argument,none,
5646-
"passing argument of non-sendable type %0 %select{into %2 context|"
5647-
"outside of %2 context}1 may introduce data races",
5648-
(Type, bool, ActorIsolation))
56495642
ERROR(non_sendable_result_type,none,
56505643
"non-sendable type %0 returned by %select{call to %3 %kind2|"
56515644
"call from %4 context to nonisolated %kind2|"

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 14 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,85 +2273,6 @@ static FuncDecl *findAnnotatableFunction(DeclContext *dc) {
22732273
return fn;
22742274
}
22752275

2276-
static bool shouldCheckSendable(Expr *expr) {
2277-
if (auto *declRef = dyn_cast<DeclRefExpr>(expr->findOriginalValue())) {
2278-
auto isolation = getActorIsolation(declRef->getDecl());
2279-
return isolation != ActorIsolation::NonisolatedUnsafe;
2280-
}
2281-
2282-
return true;
2283-
}
2284-
2285-
bool swift::diagnoseApplyArgSendability(ApplyExpr *apply, const DeclContext *declContext) {
2286-
auto isolationCrossing = apply->getIsolationCrossing();
2287-
if (!isolationCrossing.has_value())
2288-
return false;
2289-
2290-
auto fnExprType = apply->getFn()->getType();
2291-
if (!fnExprType)
2292-
return false;
2293-
2294-
// Check the 'self' argument.
2295-
if (auto *selfApply = dyn_cast<SelfApplyExpr>(apply->getFn())) {
2296-
auto *base = selfApply->getBase();
2297-
2298-
if (shouldCheckSendable(base) &&
2299-
diagnoseNonSendableTypes(
2300-
base->getType(),
2301-
declContext, /*inDerivedConformance*/Type(),
2302-
base->getStartLoc(),
2303-
diag::non_sendable_call_argument,
2304-
isolationCrossing.value().exitsIsolation(),
2305-
isolationCrossing.value().getDiagnoseIsolation()))
2306-
return true;
2307-
}
2308-
auto fnType = fnExprType->getAs<FunctionType>();
2309-
if (!fnType)
2310-
return false;
2311-
2312-
auto params = fnType->getParams();
2313-
for (unsigned paramIdx : indices(params)) {
2314-
const auto &param = params[paramIdx];
2315-
2316-
// Dig out the location of the argument.
2317-
SourceLoc argLoc = apply->getLoc();
2318-
Type argType;
2319-
bool checkSendable = true;
2320-
if (auto argList = apply->getArgs()) {
2321-
auto arg = argList->get(paramIdx);
2322-
if (arg.getStartLoc().isValid())
2323-
argLoc = arg.getStartLoc();
2324-
2325-
// Determine the type of the argument, ignoring any implicit
2326-
// conversions that could have stripped sendability.
2327-
if (Expr *argExpr = arg.getExpr()) {
2328-
checkSendable = shouldCheckSendable(argExpr);
2329-
argType = argExpr->findOriginalType();
2330-
2331-
// If this is a default argument expression, don't check Sendability
2332-
// if the argument is evaluated in the callee's isolation domain.
2333-
if (auto *defaultExpr = dyn_cast<DefaultArgumentExpr>(argExpr)) {
2334-
auto argIsolation = defaultExpr->getRequiredIsolation();
2335-
auto calleeIsolation = isolationCrossing->getCalleeIsolation();
2336-
if (argIsolation == calleeIsolation) {
2337-
continue;
2338-
}
2339-
}
2340-
}
2341-
}
2342-
2343-
if (checkSendable &&
2344-
diagnoseNonSendableTypes(
2345-
argType ? argType : param.getParameterType(),
2346-
declContext, /*inDerivedConformance*/Type(),
2347-
argLoc, diag::non_sendable_call_argument,
2348-
isolationCrossing.value().exitsIsolation(),
2349-
isolationCrossing.value().getDiagnoseIsolation()))
2350-
return true;
2351-
}
2352-
return false;
2353-
}
2354-
23552276
namespace {
23562277
/// Check for adherence to the actor isolation rules, emitting errors
23572278
/// when actor-isolated declarations are used in an unsafe manner.
@@ -2844,29 +2765,17 @@ namespace {
28442765
auto *patternBindingDecl = getTopPatternBindingDecl();
28452766
if (patternBindingDecl && patternBindingDecl->isAsyncLet()) {
28462767
// Defer diagnosing checking of non-Sendable types that are passed
2847-
// into async let to SIL level region based isolation if we have
2848-
// region based isolation enabled.
2849-
//
2850-
// We purposely do not do this for SendingArgsAndResults since that
2851-
// just triggers the actual ability to represent
2852-
// 'sending'. RegionBasedIsolation is what determines if we get the
2853-
// differing semantics.
2854-
if (!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation)) {
2855-
diagnoseNonSendableTypes(
2856-
type, getDeclContext(),
2857-
/*inDerivedConformance*/Type(), capture.getLoc(),
2858-
diag::implicit_async_let_non_sendable_capture,
2859-
decl->getName());
2860-
}
2861-
} else {
2862-
// Fallback to a generic implicit capture missing sendable
2863-
// conformance diagnostic.
2864-
diagnoseNonSendableTypes(type, getDeclContext(),
2865-
/*inDerivedConformance*/Type(),
2866-
capture.getLoc(),
2867-
diag::implicit_non_sendable_capture,
2868-
decl->getName());
2768+
// into async let to SIL level region based isolation.
2769+
return;
28692770
}
2771+
2772+
// Fallback to a generic implicit capture missing sendable
2773+
// conformance diagnostic.
2774+
diagnoseNonSendableTypes(type, getDeclContext(),
2775+
/*inDerivedConformance*/Type(),
2776+
capture.getLoc(),
2777+
diag::implicit_non_sendable_capture,
2778+
decl->getName());
28702779
} else if (fnType->isSendable()) {
28712780
diagnoseNonSendableTypes(type, getDeclContext(),
28722781
/*inDerivedConformance*/Type(),
@@ -3903,12 +3812,11 @@ namespace {
39033812
unsatisfiedIsolation, setThrows, usesDistributedThunk);
39043813
}
39053814

3906-
// Check if language features ask us to defer sendable diagnostics if so,
3907-
// don't check for sendability of arguments here.
3908-
if (!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation)) {
3909-
diagnoseApplyArgSendability(apply, getDeclContext());
3910-
}
3815+
// Sendable checking for arguments is deferred to region isolation.
39113816

3817+
// FIXME: Defer sendable checking for result types to region isolation
3818+
// always.
3819+
//
39123820
// Check for sendability of the result type if we do not have a
39133821
// sending result.
39143822
if ((!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation) ||

lib/Sema/TypeCheckConcurrency.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -644,11 +644,6 @@ bool isPotentiallyIsolatedActor(
644644
VarDecl *var, llvm::function_ref<bool(ParamDecl *)> isIsolated =
645645
[](ParamDecl *P) { return P->isIsolated(); });
646646

647-
/// Check whether the given ApplyExpr makes an unsatisfied isolation jump
648-
/// and if so, emit diagnostics for any nonsendable arguments to the apply
649-
bool diagnoseApplyArgSendability(
650-
swift::ApplyExpr *apply, const DeclContext *declContext);
651-
652647
/// If the enclosing function has @_unsafeInheritExecutorAttr, return it.
653648
AbstractFunctionDecl *enclosingUnsafeInheritsExecutor(const DeclContext *dc);
654649

test/Concurrency/issue-57376.swift

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=targeted %s -emit-sil -o /dev/null -verify -verify-additional-prefix targeted-and-complete-
1+
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=targeted %s -emit-sil -o /dev/null -verify -verify-additional-prefix targeted-
22
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix tns- -verify-additional-prefix transferring-tns-
33

44
// REQUIRES: concurrency
@@ -24,55 +24,37 @@ func testAsyncSequence1Sendable<Seq: AsyncSequence>(_ seq: Seq) async throws whe
2424
async let _ = seq.reduce(0) { $0 + $1 } // OK
2525
}
2626

27-
func testAsyncSequenceTypedPattern<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int { // expected-targeted-and-complete-note {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{54-54=, Sendable}}
28-
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{54-54=, Sendable}}
27+
func testAsyncSequenceTypedPattern<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
2928
async let result: Int = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
3029
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
31-
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
32-
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
3330
let _ = try! await result
3431
}
3532

36-
func testAsyncSequenceTypedPattern1<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int { // expected-targeted-and-complete-note {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{55-55=, Sendable}}
37-
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{55-55=, Sendable}}
33+
func testAsyncSequenceTypedPattern1<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
3834
async let _: Int = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
3935
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
40-
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
41-
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
4236
}
4337

44-
func testAsyncSequence<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int { // expected-targeted-and-complete-note {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{42-42=, Sendable}}
45-
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{42-42=, Sendable}}
38+
func testAsyncSequence<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
4639
async let result = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
4740
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
48-
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
49-
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
5041
let _ = try! await result
5142
}
5243

53-
func testAsyncSequence1<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int { // expected-targeted-and-complete-note {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{43-43=, Sendable}}
54-
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{43-43=, Sendable}}
44+
func testAsyncSequence1<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
5545
async let _ = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
5646
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
57-
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
58-
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
5947
}
6048

61-
func testAsyncSequence3<Seq>(_ seq: Seq) async throws where Seq: AsyncSequence, Seq.Element == Int { // expected-targeted-and-complete-note {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{28-28=: Sendable}}
62-
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{28-28=: Sendable}}
49+
func testAsyncSequence3<Seq>(_ seq: Seq) async throws where Seq: AsyncSequence, Seq.Element == Int {
6350
async let result = seq // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
6451
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
65-
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
66-
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
6752
let _ = await result
6853
}
6954

70-
func testAsyncSequence4<Seq>(_ seq: Seq) async throws where Seq: AsyncSequence, Seq.Element == Int { // expected-targeted-and-complete-note {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{28-28=: Sendable}}
71-
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{28-28=: Sendable}}
55+
func testAsyncSequence4<Seq>(_ seq: Seq) async throws where Seq: AsyncSequence, Seq.Element == Int {
7256
async let _ = seq // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
7357
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
74-
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
75-
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
7658
}
7759

7860
func search(query: String, entities: [String]) async throws -> [String] {

0 commit comments

Comments
 (0)