[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.
This commit is contained in:
Holly Borla
2024-07-30 22:09:23 -07:00
parent 95cff2a9d6
commit dfea802e51
5 changed files with 38 additions and 169 deletions

View File

@@ -5520,9 +5520,6 @@ ERROR(non_sendable_isolated_capture,none,
"capture of %1 with non-sendable type %0 in an isolated " "capture of %1 with non-sendable type %0 in an isolated "
"%select{local function|closure}2", "%select{local function|closure}2",
(Type, DeclName, bool)) (Type, DeclName, bool))
ERROR(implicit_async_let_non_sendable_capture,none,
"capture of %1 with non-sendable type %0 in 'async let' binding",
(Type, DeclName))
ERROR(self_capture_deinit_task,none, ERROR(self_capture_deinit_task,none,
"capture of 'self' in a closure that outlives deinit", "capture of 'self' in a closure that outlives deinit",
()) ())
@@ -5642,10 +5639,6 @@ ERROR(non_sendable_param_type,none,
"in parameter of superclass method overridden by %3 %kind2|" "in parameter of superclass method overridden by %3 %kind2|"
"in parameter of %3 '@objc' %kind2}1 cannot cross actor boundary", "in parameter of %3 '@objc' %kind2}1 cannot cross actor boundary",
(Type, unsigned, const ValueDecl *, ActorIsolation)) (Type, unsigned, const ValueDecl *, ActorIsolation))
ERROR(non_sendable_call_argument,none,
"passing argument of non-sendable type %0 %select{into %2 context|"
"outside of %2 context}1 may introduce data races",
(Type, bool, ActorIsolation))
ERROR(non_sendable_result_type,none, ERROR(non_sendable_result_type,none,
"non-sendable type %0 returned by %select{call to %3 %kind2|" "non-sendable type %0 returned by %select{call to %3 %kind2|"
"call from %4 context to nonisolated %kind2|" "call from %4 context to nonisolated %kind2|"

View File

@@ -2273,85 +2273,6 @@ static FuncDecl *findAnnotatableFunction(DeclContext *dc) {
return fn; return fn;
} }
static bool shouldCheckSendable(Expr *expr) {
if (auto *declRef = dyn_cast<DeclRefExpr>(expr->findOriginalValue())) {
auto isolation = getActorIsolation(declRef->getDecl());
return isolation != ActorIsolation::NonisolatedUnsafe;
}
return true;
}
bool swift::diagnoseApplyArgSendability(ApplyExpr *apply, const DeclContext *declContext) {
auto isolationCrossing = apply->getIsolationCrossing();
if (!isolationCrossing.has_value())
return false;
auto fnExprType = apply->getFn()->getType();
if (!fnExprType)
return false;
// Check the 'self' argument.
if (auto *selfApply = dyn_cast<SelfApplyExpr>(apply->getFn())) {
auto *base = selfApply->getBase();
if (shouldCheckSendable(base) &&
diagnoseNonSendableTypes(
base->getType(),
declContext, /*inDerivedConformance*/Type(),
base->getStartLoc(),
diag::non_sendable_call_argument,
isolationCrossing.value().exitsIsolation(),
isolationCrossing.value().getDiagnoseIsolation()))
return true;
}
auto fnType = fnExprType->getAs<FunctionType>();
if (!fnType)
return false;
auto params = fnType->getParams();
for (unsigned paramIdx : indices(params)) {
const auto &param = params[paramIdx];
// Dig out the location of the argument.
SourceLoc argLoc = apply->getLoc();
Type argType;
bool checkSendable = true;
if (auto argList = apply->getArgs()) {
auto arg = argList->get(paramIdx);
if (arg.getStartLoc().isValid())
argLoc = arg.getStartLoc();
// Determine the type of the argument, ignoring any implicit
// conversions that could have stripped sendability.
if (Expr *argExpr = arg.getExpr()) {
checkSendable = shouldCheckSendable(argExpr);
argType = argExpr->findOriginalType();
// If this is a default argument expression, don't check Sendability
// if the argument is evaluated in the callee's isolation domain.
if (auto *defaultExpr = dyn_cast<DefaultArgumentExpr>(argExpr)) {
auto argIsolation = defaultExpr->getRequiredIsolation();
auto calleeIsolation = isolationCrossing->getCalleeIsolation();
if (argIsolation == calleeIsolation) {
continue;
}
}
}
}
if (checkSendable &&
diagnoseNonSendableTypes(
argType ? argType : param.getParameterType(),
declContext, /*inDerivedConformance*/Type(),
argLoc, diag::non_sendable_call_argument,
isolationCrossing.value().exitsIsolation(),
isolationCrossing.value().getDiagnoseIsolation()))
return true;
}
return false;
}
namespace { namespace {
/// Check for adherence to the actor isolation rules, emitting errors /// Check for adherence to the actor isolation rules, emitting errors
/// when actor-isolated declarations are used in an unsafe manner. /// when actor-isolated declarations are used in an unsafe manner.
@@ -2844,29 +2765,17 @@ namespace {
auto *patternBindingDecl = getTopPatternBindingDecl(); auto *patternBindingDecl = getTopPatternBindingDecl();
if (patternBindingDecl && patternBindingDecl->isAsyncLet()) { if (patternBindingDecl && patternBindingDecl->isAsyncLet()) {
// Defer diagnosing checking of non-Sendable types that are passed // Defer diagnosing checking of non-Sendable types that are passed
// into async let to SIL level region based isolation if we have // into async let to SIL level region based isolation.
// region based isolation enabled. return;
//
// We purposely do not do this for SendingArgsAndResults since that
// just triggers the actual ability to represent
// 'sending'. RegionBasedIsolation is what determines if we get the
// differing semantics.
if (!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation)) {
diagnoseNonSendableTypes(
type, getDeclContext(),
/*inDerivedConformance*/Type(), capture.getLoc(),
diag::implicit_async_let_non_sendable_capture,
decl->getName());
}
} else {
// Fallback to a generic implicit capture missing sendable
// conformance diagnostic.
diagnoseNonSendableTypes(type, getDeclContext(),
/*inDerivedConformance*/Type(),
capture.getLoc(),
diag::implicit_non_sendable_capture,
decl->getName());
} }
// Fallback to a generic implicit capture missing sendable
// conformance diagnostic.
diagnoseNonSendableTypes(type, getDeclContext(),
/*inDerivedConformance*/Type(),
capture.getLoc(),
diag::implicit_non_sendable_capture,
decl->getName());
} else if (fnType->isSendable()) { } else if (fnType->isSendable()) {
diagnoseNonSendableTypes(type, getDeclContext(), diagnoseNonSendableTypes(type, getDeclContext(),
/*inDerivedConformance*/Type(), /*inDerivedConformance*/Type(),
@@ -3903,12 +3812,11 @@ namespace {
unsatisfiedIsolation, setThrows, usesDistributedThunk); unsatisfiedIsolation, setThrows, usesDistributedThunk);
} }
// Check if language features ask us to defer sendable diagnostics if so, // Sendable checking for arguments is deferred to region isolation.
// don't check for sendability of arguments here.
if (!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation)) {
diagnoseApplyArgSendability(apply, getDeclContext());
}
// FIXME: Defer sendable checking for result types to region isolation
// always.
//
// Check for sendability of the result type if we do not have a // Check for sendability of the result type if we do not have a
// sending result. // sending result.
if ((!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation) || if ((!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation) ||

View File

@@ -644,11 +644,6 @@ bool isPotentiallyIsolatedActor(
VarDecl *var, llvm::function_ref<bool(ParamDecl *)> isIsolated = VarDecl *var, llvm::function_ref<bool(ParamDecl *)> isIsolated =
[](ParamDecl *P) { return P->isIsolated(); }); [](ParamDecl *P) { return P->isIsolated(); });
/// Check whether the given ApplyExpr makes an unsatisfied isolation jump
/// and if so, emit diagnostics for any nonsendable arguments to the apply
bool diagnoseApplyArgSendability(
swift::ApplyExpr *apply, const DeclContext *declContext);
/// If the enclosing function has @_unsafeInheritExecutorAttr, return it. /// If the enclosing function has @_unsafeInheritExecutorAttr, return it.
AbstractFunctionDecl *enclosingUnsafeInheritsExecutor(const DeclContext *dc); AbstractFunctionDecl *enclosingUnsafeInheritsExecutor(const DeclContext *dc);

View File

@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=targeted %s -emit-sil -o /dev/null -verify -verify-additional-prefix targeted-and-complete- // RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=targeted %s -emit-sil -o /dev/null -verify -verify-additional-prefix targeted-
// 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- // 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-
// REQUIRES: concurrency // REQUIRES: concurrency
@@ -24,55 +24,37 @@ func testAsyncSequence1Sendable<Seq: AsyncSequence>(_ seq: Seq) async throws whe
async let _ = seq.reduce(0) { $0 + $1 } // OK async let _ = seq.reduce(0) { $0 + $1 } // OK
} }
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}} func testAsyncSequenceTypedPattern<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{54-54=, Sendable}}
async let result: Int = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}} async let result: Int = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}} // expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
let _ = try! await result let _ = try! await result
} }
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}} func testAsyncSequenceTypedPattern1<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{55-55=, Sendable}}
async let _: Int = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}} async let _: Int = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}} // expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
} }
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}} func testAsyncSequence<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{42-42=, Sendable}}
async let result = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}} async let result = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}} // expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
let _ = try! await result let _ = try! await result
} }
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}} func testAsyncSequence1<Seq: AsyncSequence>(_ seq: Seq) async throws where Seq.Element == Int {
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{43-43=, Sendable}}
async let _ = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}} async let _ = seq.reduce(0) { $0 + $1 } // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}} // expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
} }
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}} func testAsyncSequence3<Seq>(_ seq: Seq) async throws where Seq: AsyncSequence, Seq.Element == Int {
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{28-28=: Sendable}}
async let result = seq // expected-transferring-tns-warning {{sending 'seq' risks causing data races}} async let result = seq // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}} // expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
let _ = await result let _ = await result
} }
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}} func testAsyncSequence4<Seq>(_ seq: Seq) async throws where Seq: AsyncSequence, Seq.Element == Int {
// expected-no-transferring-tns-note @-1 {{consider making generic parameter 'Seq' conform to the 'Sendable' protocol}} {{28-28=: Sendable}}
async let _ = seq // expected-transferring-tns-warning {{sending 'seq' risks causing data races}} async let _ = seq // expected-transferring-tns-warning {{sending 'seq' risks causing data races}}
// expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}} // expected-transferring-tns-note @-1 {{sending task-isolated 'seq' into async let risks causing data races between nonisolated and task-isolated uses}}
// expected-targeted-and-complete-warning @-2 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
// expected-no-transferring-tns-warning @-3 {{capture of 'seq' with non-sendable type 'Seq' in 'async let' binding}}
} }
func search(query: String, entities: [String]) async throws -> [String] { func search(query: String, entities: [String]) async throws -> [String] {

View File

@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -verify -strict-concurrency=targeted -verify-additional-prefix targeted-and-complete- -emit-sil -o /dev/null %s // RUN: %target-swift-frontend -verify -strict-concurrency=targeted -verify-additional-prefix targeted- -emit-sil -o /dev/null %s
// RUN: %target-swift-frontend -verify -strict-concurrency=complete -verify-additional-prefix tns- -verify-additional-prefix complete-and-tns- -emit-sil -o /dev/null %s // RUN: %target-swift-frontend -verify -strict-concurrency=complete -verify-additional-prefix tns- -verify-additional-prefix complete-and-tns- -emit-sil -o /dev/null %s
// REQUIRES: concurrency // REQUIRES: concurrency
@@ -8,7 +8,6 @@
@available(SwiftStdlib 5.1, *) @available(SwiftStdlib 5.1, *)
struct NS1 { } struct NS1 { }
// expected-note @-1 {{consider making struct 'NS1' conform to the 'Sendable' protocol}} // expected-note @-1 {{consider making struct 'NS1' conform to the 'Sendable' protocol}}
// expected-targeted-and-complete-note @-2 {{consider making struct 'NS1' conform to the 'Sendable' protocol}}
@available(SwiftStdlib 5.1, *) @available(SwiftStdlib 5.1, *)
@available(*, unavailable) @available(*, unavailable)
@@ -94,7 +93,7 @@ public actor MyActor: MyProto {
public func bar<B>(aBar: B) async where B: Sendable { } public func bar<B>(aBar: B) async where B: Sendable { }
func g(ns1: NS1) async { func g(ns1: NS1) async {
await nonisolatedAsyncFunc1(ns1) // expected-targeted-and-complete-warning{{passing argument of non-sendable type 'NS1' outside of actor-isolated context may introduce data races}} await nonisolatedAsyncFunc1(ns1)
// expected-tns-warning @-1 {{sending 'ns1' risks causing data races}} // expected-tns-warning @-1 {{sending 'ns1' risks causing data races}}
// expected-tns-note @-2 {{sending 'self'-isolated 'ns1' to nonisolated global function 'nonisolatedAsyncFunc1' risks causing data races between nonisolated and 'self'-isolated uses}} // expected-tns-note @-2 {{sending 'self'-isolated 'ns1' to nonisolated global function 'nonisolatedAsyncFunc1' risks causing data races between nonisolated and 'self'-isolated uses}}
_ = await nonisolatedAsyncFunc2() // expected-warning{{non-sendable type 'NS1' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary}} _ = await nonisolatedAsyncFunc2() // expected-warning{{non-sendable type 'NS1' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary}}
@@ -252,8 +251,7 @@ struct CustomActor {
final class NonSendable { final class NonSendable {
// expected-note @-1 5 {{class 'NonSendable' does not conform to the 'Sendable' protocol}} // expected-note @-1 5 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
// TransferNonSendable emits 3 fewer errors here. // TransferNonSendable emits 3 fewer errors here.
// expected-targeted-and-complete-note @-3 7 {{class 'NonSendable' does not conform to the 'Sendable' protocol}} // expected-complete-and-tns-note @-3 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
// expected-complete-and-tns-note @-4 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
var value = "" var value = ""
@MainActor @MainActor
@@ -263,14 +261,12 @@ final class NonSendable {
func call() async { func call() async {
await update() await update()
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 'self' risks causing data races}}
// expected-tns-warning @-2 {{sending 'self' risks causing data races}} // expected-tns-note @-2 {{sending task-isolated 'self' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and task-isolated uses}}
// 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}}
await self.update() await self.update()
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 'self' risks causing data races}}
// expected-tns-warning @-2 {{sending 'self' risks causing data races}} // expected-tns-note @-2 {{sending task-isolated 'self' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and task-isolated uses}}
// 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}}
_ = await x _ = await x
// expected-warning@-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to main actor-isolated property 'x' cannot cross actor boundary}} // expected-warning@-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to main actor-isolated property 'x' cannot cross actor boundary}}
@@ -294,9 +290,8 @@ final class NonSendable {
func testNonSendableBaseArg() async { func testNonSendableBaseArg() async {
let t = NonSendable() let t = NonSendable()
await t.update() await t.update()
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 't' risks causing data races}}
// expected-tns-warning @-2 {{sending 't' risks causing data races}} // expected-tns-note @-2 {{sending 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}}
// expected-tns-note @-3 {{sending 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}}
_ = await t.x _ = await t.x
// expected-warning @-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to main actor-isolated property 'x' cannot cross actor boundary}} // expected-warning @-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to main actor-isolated property 'x' cannot cross actor boundary}}
@@ -308,11 +303,10 @@ func testNonSendableBaseArg() async {
func testNonSendableBaseArg2() async { func testNonSendableBaseArg2() async {
let t = NonSendable() let t = NonSendable()
await t.update() await t.update()
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 't' risks causing data races}}
// expected-tns-warning @-2 {{sending 't' risks causing data races}}
// TODO: Improve the diagnostic so that we say custom actor isolated instead since t.y // TODO: Improve the diagnostic so that we say custom actor isolated instead since t.y
// is custom actor isolated. // is custom actor isolated.
// expected-tns-note @-5 {{sending 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}} // expected-tns-note @-4 {{sending 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}}
_ = await t.y _ = await t.y
// expected-warning @-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to global actor 'CustomActor'-isolated property 'y' cannot cross actor boundary}} // expected-warning @-1 {{non-sendable type 'NonSendable' passed in implicitly asynchronous call to global actor 'CustomActor'-isolated property 'y' cannot cross actor boundary}}
@@ -324,9 +318,8 @@ func testNonSendableBaseArg2() async {
func testNonSendableBaseArg3() async { func testNonSendableBaseArg3() async {
let t = NonSendable() let t = NonSendable()
await t.update() await t.update()
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 't' risks causing data races}}
// expected-tns-warning @-2 {{sending 't' risks causing data races}} // expected-tns-note @-2 {{sending 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}}
// expected-tns-note @-3 {{sending 't' to main actor-isolated instance method 'update()' risks causing data races between main actor-isolated and local nonisolated uses}}
_ = t.z _ = t.z
// expected-tns-note @-1 {{access can happen concurrently}} // expected-tns-note @-1 {{access can happen concurrently}}
@@ -343,15 +336,13 @@ func callNonisolatedAsyncClosure(
g: (NonSendable) async -> Void g: (NonSendable) async -> Void
) async { ) async {
await g(ns) await g(ns)
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' outside of main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 'ns' risks causing data races}}
// expected-tns-warning @-2 {{sending 'ns' risks causing data races}} // expected-tns-note @-2 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
let f: (NonSendable) async -> () = globalSendable // okay let f: (NonSendable) async -> () = globalSendable // okay
await f(ns) await f(ns)
// expected-targeted-and-complete-warning@-1 {{passing argument of non-sendable type 'NonSendable' outside of main actor-isolated context may introduce data races}} // expected-tns-warning @-1 {{sending 'ns' risks causing data races}}
// expected-tns-warning @-2 {{sending 'ns' risks causing data races}} // expected-tns-note @-2 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
} }
@available(SwiftStdlib 5.1, *) @available(SwiftStdlib 5.1, *)