mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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:
@@ -5520,9 +5520,6 @@ ERROR(non_sendable_isolated_capture,none,
|
||||
"capture of %1 with non-sendable type %0 in an isolated "
|
||||
"%select{local function|closure}2",
|
||||
(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,
|
||||
"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 %3 '@objc' %kind2}1 cannot cross actor boundary",
|
||||
(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,
|
||||
"non-sendable type %0 returned by %select{call to %3 %kind2|"
|
||||
"call from %4 context to nonisolated %kind2|"
|
||||
|
||||
@@ -2273,85 +2273,6 @@ static FuncDecl *findAnnotatableFunction(DeclContext *dc) {
|
||||
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 ¶m = 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 {
|
||||
/// Check for adherence to the actor isolation rules, emitting errors
|
||||
/// when actor-isolated declarations are used in an unsafe manner.
|
||||
@@ -2844,29 +2765,17 @@ namespace {
|
||||
auto *patternBindingDecl = getTopPatternBindingDecl();
|
||||
if (patternBindingDecl && patternBindingDecl->isAsyncLet()) {
|
||||
// Defer diagnosing checking of non-Sendable types that are passed
|
||||
// into async let to SIL level region based isolation if we have
|
||||
// region based isolation enabled.
|
||||
//
|
||||
// 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());
|
||||
// into async let to SIL level region based isolation.
|
||||
return;
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
diagnoseNonSendableTypes(type, getDeclContext(),
|
||||
/*inDerivedConformance*/Type(),
|
||||
@@ -3903,12 +3812,11 @@ namespace {
|
||||
unsatisfiedIsolation, setThrows, usesDistributedThunk);
|
||||
}
|
||||
|
||||
// Check if language features ask us to defer sendable diagnostics if so,
|
||||
// don't check for sendability of arguments here.
|
||||
if (!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation)) {
|
||||
diagnoseApplyArgSendability(apply, getDeclContext());
|
||||
}
|
||||
// Sendable checking for arguments is deferred to region isolation.
|
||||
|
||||
// FIXME: Defer sendable checking for result types to region isolation
|
||||
// always.
|
||||
//
|
||||
// Check for sendability of the result type if we do not have a
|
||||
// sending result.
|
||||
if ((!ctx.LangOpts.hasFeature(Feature::RegionBasedIsolation) ||
|
||||
|
||||
@@ -644,11 +644,6 @@ bool isPotentiallyIsolatedActor(
|
||||
VarDecl *var, llvm::function_ref<bool(ParamDecl *)> 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.
|
||||
AbstractFunctionDecl *enclosingUnsafeInheritsExecutor(const DeclContext *dc);
|
||||
|
||||
|
||||
@@ -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-
|
||||
|
||||
// REQUIRES: concurrency
|
||||
@@ -24,55 +24,37 @@ func testAsyncSequence1Sendable<Seq: AsyncSequence>(_ seq: Seq) async throws whe
|
||||
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}}
|
||||
// expected-no-transferring-tns-note @-1 {{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 {
|
||||
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-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
|
||||
}
|
||||
|
||||
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}}
|
||||
// expected-no-transferring-tns-note @-1 {{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 {
|
||||
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-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}}
|
||||
// expected-no-transferring-tns-note @-1 {{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 {
|
||||
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-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
|
||||
}
|
||||
|
||||
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}}
|
||||
// expected-no-transferring-tns-note @-1 {{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 {
|
||||
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-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}}
|
||||
// expected-no-transferring-tns-note @-1 {{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 {
|
||||
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-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
|
||||
}
|
||||
|
||||
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}}
|
||||
// expected-no-transferring-tns-note @-1 {{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 {
|
||||
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-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] {
|
||||
|
||||
@@ -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
|
||||
|
||||
// REQUIRES: concurrency
|
||||
@@ -8,7 +8,6 @@
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
struct NS1 { }
|
||||
// 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(*, unavailable)
|
||||
@@ -94,7 +93,7 @@ public actor MyActor: MyProto {
|
||||
public func bar<B>(aBar: B) async where B: Sendable { }
|
||||
|
||||
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-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}}
|
||||
@@ -252,8 +251,7 @@ struct CustomActor {
|
||||
final class NonSendable {
|
||||
// expected-note @-1 5 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
|
||||
// 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 @-4 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
|
||||
// expected-complete-and-tns-note @-3 {{class 'NonSendable' does not conform to the 'Sendable' protocol}}
|
||||
var value = ""
|
||||
|
||||
@MainActor
|
||||
@@ -263,14 +261,12 @@ final class NonSendable {
|
||||
|
||||
func call() async {
|
||||
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 @-2 {{sending 'self' risks causing data races}}
|
||||
// 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}}
|
||||
// expected-tns-warning @-1 {{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}}
|
||||
|
||||
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 @-2 {{sending 'self' risks causing data races}}
|
||||
// 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}}
|
||||
// expected-tns-warning @-1 {{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}}
|
||||
|
||||
_ = await x
|
||||
// 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 {
|
||||
let t = NonSendable()
|
||||
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 @-2 {{sending 't' risks causing data races}}
|
||||
// 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}}
|
||||
// expected-tns-warning @-1 {{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}}
|
||||
|
||||
_ = 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}}
|
||||
@@ -308,11 +303,10 @@ func testNonSendableBaseArg() async {
|
||||
func testNonSendableBaseArg2() async {
|
||||
let t = NonSendable()
|
||||
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 @-2 {{sending 't' risks causing data races}}
|
||||
// expected-tns-warning @-1 {{sending 't' risks causing data races}}
|
||||
// TODO: Improve the diagnostic so that we say custom actor isolated instead since t.y
|
||||
// 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
|
||||
// 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 {
|
||||
let t = NonSendable()
|
||||
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 @-2 {{sending 't' risks causing data races}}
|
||||
// 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}}
|
||||
// expected-tns-warning @-1 {{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}}
|
||||
|
||||
_ = t.z
|
||||
// expected-tns-note @-1 {{access can happen concurrently}}
|
||||
@@ -343,15 +336,13 @@ func callNonisolatedAsyncClosure(
|
||||
g: (NonSendable) async -> Void
|
||||
) async {
|
||||
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 @-2 {{sending 'ns' risks causing data races}}
|
||||
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
|
||||
// expected-tns-warning @-1 {{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}}
|
||||
|
||||
let f: (NonSendable) async -> () = globalSendable // okay
|
||||
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 @-2 {{sending 'ns' risks causing data races}}
|
||||
// expected-tns-note @-3 {{sending main actor-isolated 'ns' to nonisolated callee risks causing data races between nonisolated and main actor-isolated uses}}
|
||||
// expected-tns-warning @-1 {{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}}
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
|
||||
Reference in New Issue
Block a user