Skip to content

Commit 6ef6b25

Browse files
authored
Merge pull request #75579 from hborla/delete-sema-sendable-checking
[Concurrency] Delete sendable checking subsumed by region isolation.
2 parents 45ee3ee + dfea802 commit 6ef6b25

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)