From 933f8eb8a0d0aa39063627d94b02185155d464cc Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 5 Aug 2024 08:13:06 -0700 Subject: [PATCH 1/5] [Concurrency] Split up the non-Sendable argument diagnostics and improve wording. Splitting up the diagnostic into separate diagnostics based on the reference kind is easier for me to read. The wording of the error message now puts the problem -- crossing an isolation boundary -- at the center of the message, and attempts to clarify how the value crosses an isolation boundary. E.g. for the witness diagnostics, the value crosses an isolation boundary when calling the witness through the protocol requirement in generic code. This change does not add any additional information to the diagnostics, but it'd be valuable to show both the source and destination isolation. --- include/swift/AST/DiagnosticsSema.def | 29 +++++++++++----- lib/Sema/TypeCheckConcurrency.cpp | 34 +++++++++++++++---- test/Concurrency/actor_inout_isolation.swift | 6 ++-- test/Concurrency/actor_isolation.swift | 6 ++-- test/Concurrency/actor_isolation_swift6.swift | 4 +-- .../concurrent_value_checking.swift | 4 +-- .../Concurrency/global_actor_serialized.swift | 2 +- test/Concurrency/sendable_checking.swift | 20 +++++------ .../sendable_override_checking.swift | 4 +-- 9 files changed, 72 insertions(+), 37 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 0f602c12b5f8c..226d1c2c4bcfb 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5635,14 +5635,27 @@ NOTE(in_derived_conformance, none, NOTE(in_derived_witness, none, "in %0 %1 for derived conformance to %2", (DescriptiveDeclKind, DeclName, Type)) -ERROR(non_sendable_param_type,none, - "non-sendable type %0 %select{passed in call to %3 %kind2|" - "exiting %3 context in call to nonisolated %kind2|" - "passed in implicitly asynchronous call to %3 %kind2|" - "in parameter of the protocol requirement satisfied by %3 %kind2|" - "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_arg_into_actor,none, + "non-sendable type %0 cannot be sent into %2 context in call to %kind1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_arg_exits_actor,none, + "non-sendable type %0 cannot exit %2 context in call to nonisolated " + "%kind1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_param_in_witness,none, + "non-sendable parameter type %0 cannot be sent from protocol " + "requirement %1 into %2 implementation", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_param_in_override,none, + "non-sendable parameter type %0 cannot be sent from superclass " + "%kind1 into %2 override", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_param_in_objc,none, + "non-sendable parameter type %0 of %2 '@objc' %kind1 cannot cross actor " + "boundary", + (Type, const ValueDecl *, 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|" diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 254d6b5d47c33..f50ac762a9e33 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1121,6 +1121,28 @@ bool swift::diagnoseNonSendableTypes( return anyMissing; } +static +Diag +getSendableParamDiag(SendableCheckReason refKind) { + switch (refKind) { + case SendableCheckReason::CrossActor: + case SendableCheckReason::SynchronousAsAsync: + return diag::non_sendable_arg_into_actor; + + case SendableCheckReason::ExitingActor: + return diag::non_sendable_arg_exits_actor; + + case SendableCheckReason::Conformance: + return diag::non_sendable_param_in_witness; + + case SendableCheckReason::Override: + return diag::non_sendable_param_in_override; + + case SendableCheckReason::ObjC: + return diag::non_sendable_param_in_objc; + } +} + bool swift::diagnoseNonSendableTypesInReference( Expr *base, ConcreteDeclRef declRef, const DeclContext *fromDC, SourceLoc refLoc, SendableCheckReason refKind, @@ -1155,8 +1177,8 @@ bool swift::diagnoseNonSendableTypesInReference( base->getType(), fromDC, derivedConformanceType, base->getStartLoc(), - diag::non_sendable_param_type, - (unsigned)refKind, declRef.getDecl(), + getSendableParamDiag(refKind), + declRef.getDecl(), getActorIsolation())) return true; } @@ -1171,8 +1193,8 @@ bool swift::diagnoseNonSendableTypesInReference( if (diagnoseNonSendableTypes( paramType, fromDC, derivedConformanceType, refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc, - diag::non_sendable_param_type, - (unsigned)refKind, function, getActorIsolation())) + getSendableParamDiag(refKind), + function, getActorIsolation())) return true; } } @@ -1217,8 +1239,8 @@ bool swift::diagnoseNonSendableTypesInReference( if (diagnoseNonSendableTypes( paramType, fromDC, derivedConformanceType, refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc, - diag::non_sendable_param_type, - (unsigned)refKind, subscript, getActorIsolation())) + getSendableParamDiag(refKind), + subscript, getActorIsolation())) return true; } } diff --git a/test/Concurrency/actor_inout_isolation.swift b/test/Concurrency/actor_inout_isolation.swift index 85f8f2463789c..bea98d266c626 100644 --- a/test/Concurrency/actor_inout_isolation.swift +++ b/test/Concurrency/actor_inout_isolation.swift @@ -119,7 +119,7 @@ extension TestActor { func passStateIntoDifferentClassMethod() async { let other = NonAsyncClass() let otherCurry = other.modifyOtherAsync - // expected-targeted-complete-tns-warning @-1 {{non-sendable type 'NonAsyncClass' exiting actor-isolated context in call to nonisolated instance method 'modifyOtherAsync' cannot cross actor boundary}} + // expected-targeted-complete-tns-warning @-1 {{non-sendable type 'NonAsyncClass' cannot exit actor-isolated context in call to nonisolated instance method 'modifyOtherAsync'}} await other.modifyOtherAsync(&value2) // expected-error @-1 {{actor-isolated property 'value2' cannot be passed 'inout' to 'async' function call}} @@ -288,11 +288,11 @@ actor ProtectArray { func test() async { // FIXME: this is invalid too! _ = await array.mutateAsynchronously - // expected-targeted-complete-tns-warning@-1 {{non-sendable type '@lvalue [Int]' exiting actor-isolated context in call to nonisolated property 'mutateAsynchronously' cannot cross actor boundary}} + // expected-targeted-complete-tns-warning@-1 {{non-sendable type '@lvalue [Int]' cannot exit actor-isolated context in call to nonisolated property 'mutateAsynchronously'}} _ = await array[mutateAsynchronously: 0] // expected-error@-1 {{actor-isolated property 'array' cannot be passed 'inout' to 'async' function call}} - // expected-targeted-complete-tns-warning@-2 {{non-sendable type 'inout Array' exiting actor-isolated context in call to nonisolated subscript 'subscript(mutateAsynchronously:)' cannot cross actor boundary}} + // expected-targeted-complete-tns-warning@-2 {{non-sendable type 'inout Array' cannot exit actor-isolated context in call to nonisolated subscript 'subscript(mutateAsynchronously:)'}} await passToAsync(array[0]) diff --git a/test/Concurrency/actor_isolation.swift b/test/Concurrency/actor_isolation.swift index 81c694526a019..172e53edacf67 100644 --- a/test/Concurrency/actor_isolation.swift +++ b/test/Concurrency/actor_isolation.swift @@ -153,13 +153,13 @@ func checkIsolationValueType(_ formance: InferredFromConformance, // these still do need an await in Swift 5 _ = await ext.point // expected-warning {{non-sendable type 'Point' in implicitly asynchronous access to main actor-isolated property 'point' cannot cross actor boundary}} _ = await anno.point // expected-warning {{non-sendable type 'Point' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated property 'point' cannot cross actor boundary}} - // expected-warning@-1 {{non-sendable type 'NoGlobalActorValueType' passed in implicitly asynchronous call to global actor 'SomeGlobalActor'-isolated property 'point' cannot cross actor boundary}} + // expected-warning@-1 {{non-sendable type 'NoGlobalActorValueType' cannot be sent into global actor 'SomeGlobalActor'-isolated context in call to property 'point'}} _ = formance.counter _ = anno.counter // these will always need an await - _ = await (formance as MainCounter).counter // expected-warning {{non-sendable type 'any MainCounter' passed in implicitly asynchronous call to main actor-isolated property 'counter' cannot cross actor boundary}} + _ = await (formance as MainCounter).counter // expected-warning {{non-sendable type 'any MainCounter' cannot be sent into main actor-isolated context in call to property 'counter'}} _ = await ext[1] _ = await formance.ticker _ = await ext.polygon // expected-warning {{non-sendable type '[Point]' in implicitly asynchronous access to main actor-isolated property 'polygon' cannot cross actor boundary}} @@ -1662,7 +1662,7 @@ actor SafeMutatingCall { @MainActor -func testLocalFunctoinIsolation() { +func testLocalFunctionIsolation() { func isolatedLocalFn() {} // expected-note@-1 {{calls to local function 'isolatedLocalFn()' from outside of its actor context are implicitly asynchronous}} // expected-note@-2 {{main actor isolation inferred from enclosing context}} diff --git a/test/Concurrency/actor_isolation_swift6.swift b/test/Concurrency/actor_isolation_swift6.swift index d2f433fc85cc5..aa30c0aeaca4b 100644 --- a/test/Concurrency/actor_isolation_swift6.swift +++ b/test/Concurrency/actor_isolation_swift6.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -disable-availability-checking -swift-version 6 -emit-sil -o /dev/null -verify -enable-upcoming-feature GlobalActorIsolatedTypesUsability %s +// RUN: %target-swift-frontend -disable-availability-checking -swift-version 6 -emit-sil -o /dev/null -verify %s // REQUIRES: concurrency // REQUIRES: asserts @@ -65,7 +65,7 @@ func checkIsolationValueType(_ formance: InferredFromConformance, // these do need await, regardless of reference or value type _ = await (formance as any MainCounter).counter - // expected-error@-1 {{non-sendable type 'any MainCounter' passed in implicitly asynchronous call to main actor-isolated property 'counter' cannot cross actor boundary}} + // expected-error@-1 {{non-sendable type 'any MainCounter' cannot be sent into main actor-isolated context in call to property 'counter'}} _ = await ext[1] _ = await formance.ticker _ = await ext.polygon diff --git a/test/Concurrency/concurrent_value_checking.swift b/test/Concurrency/concurrent_value_checking.swift index 7301931c6ad6e..362d0b6eae880 100644 --- a/test/Concurrency/concurrent_value_checking.swift +++ b/test/Concurrency/concurrent_value_checking.swift @@ -270,7 +270,7 @@ protocol AsyncProto { } extension A1: AsyncProto { - func asyncMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable type 'NotConcurrent' in parameter of the protocol requirement satisfied by actor-isolated instance method 'asyncMethod' cannot cross actor boundary}} + func asyncMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable parameter type 'NotConcurrent' cannot be sent from protocol requirement 'asyncMethod' into actor-isolated implementation}} } protocol MainActorProto { @@ -279,7 +279,7 @@ protocol MainActorProto { class SomeClass: MainActorProto { @SomeGlobalActor - func asyncMainMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable type 'NotConcurrent' in parameter of the protocol requirement satisfied by global actor 'SomeGlobalActor'-isolated instance method 'asyncMainMethod' cannot cross actor boundary}} + func asyncMainMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable parameter type 'NotConcurrent' cannot be sent from protocol requirement 'asyncMainMethod' into global actor 'SomeGlobalActor'-isolated implementation}} } // ---------------------------------------------------------------------- diff --git a/test/Concurrency/global_actor_serialized.swift b/test/Concurrency/global_actor_serialized.swift index f116b6cb2277a..5c802f1dcdf96 100644 --- a/test/Concurrency/global_actor_serialized.swift +++ b/test/Concurrency/global_actor_serialized.swift @@ -14,5 +14,5 @@ import SerializedStruct // expected-warning {{add '@preconcurrency' to treat 'Se // use it to force the right checks happen. func test() async -> Int { let x = MySerializedStruct() - return await x.counter // expected-error {{non-sendable type 'MySerializedStruct' passed in implicitly asynchronous call to main actor-isolated property 'counter' cannot cross actor boundary}} + return await x.counter // expected-error {{non-sendable type 'MySerializedStruct' cannot be sent into main actor-isolated context in call to property 'counter'}} } diff --git a/test/Concurrency/sendable_checking.swift b/test/Concurrency/sendable_checking.swift index d39fffb43ca8d..a063c215f36c6 100644 --- a/test/Concurrency/sendable_checking.swift +++ b/test/Concurrency/sendable_checking.swift @@ -142,12 +142,12 @@ protocol P { func foo(x : () -> ()) -> () {} func bar(x : () -> ()) -> () {} - // expected-warning@-1 {{non-sendable type '() -> ()' in parameter of the protocol requirement satisfied by actor-isolated instance method 'bar(x:)' cannot cross actor boundary}} + // expected-warning@-1 {{non-sendable parameter type '() -> ()' cannot be sent from protocol requirement 'bar(x:)' into actor-isolated implementation}} func foo2(x : T) -> () {} func bar2(x : T) -> () {} - // expected-warning@-1 {{non-sendable type 'T' in parameter of the protocol requirement satisfied by actor-isolated instance method 'bar2(x:)' cannot cross actor boundary}} + // expected-warning@-1 {{non-sendable parameter type 'T' cannot be sent from protocol requirement 'bar2(x:)' into actor-isolated implementation}} } @available(SwiftStdlib 5.1, *) @@ -174,12 +174,12 @@ class Sub : Super { override nonisolated func foo(x : () -> ()) async {} override nonisolated func bar(x : () -> ()) async {} - // expected-warning@-1 {{non-sendable type '() -> ()' in parameter of superclass method overridden by nonisolated instance method 'bar(x:)' cannot cross actor boundary}} + // expected-warning@-1 {{non-sendable parameter type '() -> ()' cannot be sent from superclass instance method 'bar(x:)' into nonisolated override}} override nonisolated func foo2(x: T) async {} override nonisolated func bar2(x: T) async {} - // expected-warning@-1 {{non-sendable type 'T' in parameter of superclass method overridden by nonisolated instance method 'bar2(x:)' cannot cross actor boundary}} + // expected-warning@-1 {{non-sendable parameter type 'T' cannot be sent from superclass instance method 'bar2(x:)' into nonisolated override}} } @available(SwiftStdlib 5.1, *) @@ -216,8 +216,8 @@ class SuperWUnsafeSubscript { class SubWUnsafeSubscript : SuperWUnsafeSubscript { override nonisolated subscript(x : T) -> Int { get async { - // expected-warning@-2{{non-sendable type 'T' in parameter of superclass method overridden by nonisolated subscript 'subscript(_:)' cannot cross actor boundary}} - // expected-warning@-2{{non-sendable type 'T' in parameter of superclass method overridden by nonisolated getter for subscript 'subscript(_:)' cannot cross actor boundary}} + // expected-warning@-2{{non-sendable parameter type 'T' cannot be sent from superclass subscript 'subscript(_:)' into nonisolated override}} + // expected-warning@-2{{non-sendable parameter type 'T' cannot be sent from superclass getter for subscript 'subscript(_:)' into nonisolated override}} // there really shouldn't be two warnings produced here, see rdar://110846040 (Sendable diagnostics reported twice for subscript getters) return 0 } @@ -269,10 +269,10 @@ final class NonSendable { // 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}} + // expected-warning@-1 {{non-sendable type 'NonSendable' cannot be sent into main actor-isolated context in call to property 'x'}} _ = await self.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' cannot be sent into main actor-isolated context in call to property 'x'}} } @MainActor @@ -294,7 +294,7 @@ func testNonSendableBaseArg() async { // 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}} + // expected-warning @-1 {{non-sendable type 'NonSendable' cannot be sent into main actor-isolated context in call to property 'x'}} // expected-tns-note @-2 {{access can happen concurrently}} } @@ -309,7 +309,7 @@ func testNonSendableBaseArg2() async { // 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}} + // expected-warning @-1 {{non-sendable type 'NonSendable' cannot be sent into global actor 'CustomActor'-isolated context in call to property 'y'}} // expected-tns-note @-2 {{access can happen concurrently}} } diff --git a/test/Concurrency/sendable_override_checking.swift b/test/Concurrency/sendable_override_checking.swift index 3ee831ef1b416..d89f5d9ea1272 100644 --- a/test/Concurrency/sendable_override_checking.swift +++ b/test/Concurrency/sendable_override_checking.swift @@ -24,10 +24,10 @@ class Super { @available(SwiftStdlib 5.1, *) class Sub: Super { @MainActor override func f(_: NotSendable) async { } - // expected-warning@-1{{non-sendable type 'NotSendable' in parameter of superclass method overridden by main actor-isolated instance method 'f' cannot cross actor boundary}} + // expected-warning@-1{{non-sendable parameter type 'NotSendable' cannot be sent from superclass instance method 'f' into main actor-isolated override}} nonisolated override func g1(_: NotSendable) { } // okay, synchronous nonisolated override func g2(_: NotSendable) async { } - // expected-warning@-1{{non-sendable type 'NotSendable' in parameter of superclass method overridden by nonisolated instance method 'g2' cannot cross actor boundary}} + // expected-warning@-1{{non-sendable parameter type 'NotSendable' cannot be sent from superclass instance method 'g2' into nonisolated override}} } From bd1653e4979402bedc77ba73c46b0d4b9ca7a166 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 5 Aug 2024 09:56:11 -0700 Subject: [PATCH 2/5] [Concurrency] Split up the non-Sendable result diagnostics and improve wording. --- include/swift/AST/DiagnosticsSema.def | 35 ++++++++---- lib/Sema/TypeCheckConcurrency.cpp | 53 ++++++++++++++----- test/ClangImporter/objc_async.swift | 4 +- .../actor_call_implicitly_async.swift | 10 ++-- .../concurrent_value_checking.swift | 6 +-- test/Concurrency/sendable_checking.swift | 2 +- .../sendable_conformance_checking.swift | 10 ++-- .../transfernonsendable_asynclet.swift | 4 +- ...nonsendable_defer_and_typecheck_only.swift | 6 +-- .../transfernonsendable_sending_results.swift | 4 +- 10 files changed, 88 insertions(+), 46 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 226d1c2c4bcfb..f65526f6b7fd0 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5656,18 +5656,31 @@ ERROR(non_sendable_param_in_objc,none, "boundary", (Type, const ValueDecl *, 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|" - "implicitly asynchronous call to %3 %kind2|" - "%3 %kind2 satisfying protocol requirement|" - "%3 overriding %kind2|" - "%3 '@objc' %kind2}1 cannot cross actor boundary", - (Type, unsigned, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_result_into_actor,none, + "non-sendable result type %0 cannot be sent from %2 context in call " + "to %kind1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_result_exits_actor,none, + "non-sendable result type %0 cannot exit %2 context in call to " + "nonisolated %kind1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_result_in_witness,none, + "non-sendable type %0 cannot be returned from %2 implementation " + "to caller of protocol requirement %1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_result_in_override,none, + "non-sendable type %0 cannot be returned from %2 override to " + "caller of superclass %kind1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_result_in_objc,none, + "non-sendable type %0 returned by %2 '@objc' %kind1 cannot cross " + "actor boundary", + (Type, const ValueDecl *, ActorIsolation)) + ERROR(non_sendable_call_result_type,none, - "non-sendable type %0 returned by %select{|implicitly async }1" - "call to %2 function cannot cross actor boundary", - (Type, bool, ActorIsolation)) + "non-sendable result type %0 cannot be sent from %1 context in call " + "to async function", + (Type, ActorIsolation)) ERROR(non_sendable_property_type,none, "non-sendable type %0 in %select{" "%select{asynchronous access to %4 %kind1|" diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index f50ac762a9e33..f22164437ae22 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1143,6 +1143,28 @@ getSendableParamDiag(SendableCheckReason refKind) { } } +static +Diag +getSendableResultDiag(SendableCheckReason refKind) { + switch (refKind) { + case SendableCheckReason::CrossActor: + case SendableCheckReason::SynchronousAsAsync: + return diag::non_sendable_result_into_actor; + + case SendableCheckReason::ExitingActor: + return diag::non_sendable_result_exits_actor; + + case SendableCheckReason::Conformance: + return diag::non_sendable_result_in_witness; + + case SendableCheckReason::Override: + return diag::non_sendable_result_in_override; + + case SendableCheckReason::ObjC: + return diag::non_sendable_result_in_objc; + } +} + bool swift::diagnoseNonSendableTypesInReference( Expr *base, ConcreteDeclRef declRef, const DeclContext *fromDC, SourceLoc refLoc, SendableCheckReason refKind, @@ -1207,8 +1229,8 @@ bool swift::diagnoseNonSendableTypesInReference( if (diagnoseNonSendableTypes( resultType, fromDC, derivedConformanceType, refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc, - diag::non_sendable_result_type, - (unsigned)refKind, func, getActorIsolation())) + getSendableResultDiag(refKind), + func, getActorIsolation())) return true; } } @@ -1251,8 +1273,8 @@ bool swift::diagnoseNonSendableTypesInReference( if (diagnoseNonSendableTypes( resultType, fromDC, derivedConformanceType, refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc, - diag::non_sendable_result_type, - (unsigned)refKind, subscript, getActorIsolation())) + getSendableResultDiag(refKind), + subscript, getActorIsolation())) return true; } @@ -3871,14 +3893,21 @@ namespace { fnType->getResult().getPointer(); }; - if (!willDoubleError() && - diagnoseNonSendableTypes(fnType->getResult(), getDeclContext(), - /*inDerivedConformance*/ Type(), - apply->getLoc(), - diag::non_sendable_call_result_type, - apply->isImplicitlyAsync().has_value(), - *unsatisfiedIsolation)) { - return true; + if (!willDoubleError()) { + if (calleeDecl) { + return diagnoseNonSendableTypes(fnType->getResult(), getDeclContext(), + /*inDerivedConformance*/ Type(), + apply->getLoc(), + diag::non_sendable_result_into_actor, + calleeDecl, + *unsatisfiedIsolation); + } + + return diagnoseNonSendableTypes(fnType->getResult(), getDeclContext(), + /*inDerivedConformance*/ Type(), + apply->getLoc(), + diag::non_sendable_call_result_type, + *unsatisfiedIsolation); } } diff --git a/test/ClangImporter/objc_async.swift b/test/ClangImporter/objc_async.swift index 5acf5ee969aed..442f7994c72d1 100644 --- a/test/ClangImporter/objc_async.swift +++ b/test/ClangImporter/objc_async.swift @@ -322,12 +322,12 @@ func check() async { _ = await BarFrame() _ = await FooFrame() _ = await BazFrame() - // expected-warning@-1 {{non-sendable type 'BazFrame' returned by implicitly async call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary; this is an error in the Swift 6 language mode}} + // expected-warning@-1 {{non-sendable result type 'BazFrame' cannot be sent from global actor 'SomeGlobalActor'-isolated context in call to initializer 'init()'; this is an error in the Swift 6 language mode}} _ = await BarFrame(size: 0) _ = await FooFrame(size: 0) _ = await BazFrame(size: 0) - // expected-warning@-1 {{non-sendable type 'BazFrame' returned by implicitly async call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary; this is an error in the Swift 6 language mode}} + // expected-warning@-1 {{non-sendable result type 'BazFrame' cannot be sent from global actor 'SomeGlobalActor'-isolated context in call to initializer 'init(size:)'; this is an error in the Swift 6 language mode}} } @available(SwiftStdlib 5.5, *) diff --git a/test/Concurrency/actor_call_implicitly_async.swift b/test/Concurrency/actor_call_implicitly_async.swift index d832fbf3ab34e..8feebc0682ffc 100644 --- a/test/Concurrency/actor_call_implicitly_async.swift +++ b/test/Concurrency/actor_call_implicitly_async.swift @@ -353,23 +353,23 @@ actor Calculator { @OrangeActor func doSomething() async { let _ = (await bananaAdd(1))(2) - // expected-warning@-1{{non-sendable type '(Int) -> Int' returned by implicitly async call to global actor 'BananaActor'-isolated function cannot cross actor boundary}} + // expected-warning@-1{{non-sendable result type '(Int) -> Int' cannot be sent from global actor 'BananaActor'-isolated context in call to global function 'bananaAdd'}} // expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}} let _ = await (await bananaAdd(1))(2) // expected-warning{{no 'async' operations occur within 'await' expression}} - // expected-warning@-1{{non-sendable type '(Int) -> Int' returned by implicitly async call to global actor 'BananaActor'-isolated function cannot cross actor boundary}} + // expected-warning@-1{{non-sendable result type '(Int) -> Int' cannot be sent from global actor 'BananaActor'-isolated context in call to global function 'bananaAdd'}} // expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}} let calc = Calculator() let _ = (await calc.addCurried(1))(2) - // expected-warning@-1{{non-sendable type '(Int) -> Int' returned by implicitly async call to actor-isolated function cannot cross actor boundary}} + // expected-warning@-1{{non-sendable result type '(Int) -> Int' cannot be sent from actor-isolated context in call to instance method 'addCurried'}} // expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}} let _ = await (await calc.addCurried(1))(2) // expected-warning{{no 'async' operations occur within 'await' expression}} - // expected-warning@-1{{non-sendable type '(Int) -> Int' returned by implicitly async call to actor-isolated function cannot cross actor boundary}} + // expected-warning@-1{{non-sendable result type '(Int) -> Int' cannot be sent from actor-isolated context in call to instance method 'addCurried'}} // expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}} let plusOne = await calc.addCurried(await calc.add(0, 1)) - // expected-warning@-1{{non-sendable type '(Int) -> Int' returned by implicitly async call to actor-isolated function cannot cross actor boundary}} + // expected-warning@-1{{non-sendable result type '(Int) -> Int' cannot be sent from actor-isolated context in call to instance method 'addCurried'}} // expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}} let _ = plusOne(2) } diff --git a/test/Concurrency/concurrent_value_checking.swift b/test/Concurrency/concurrent_value_checking.swift index 362d0b6eae880..7317d815d1927 100644 --- a/test/Concurrency/concurrent_value_checking.swift +++ b/test/Concurrency/concurrent_value_checking.swift @@ -102,7 +102,7 @@ extension A1 { _ = other.localLet // expected-warning{{non-sendable type 'NotConcurrent' in implicitly asynchronous access to actor-isolated property 'localLet' cannot cross actor boundary}} // expected-warning@-1 {{expression is 'async' but is not marked with 'await'}} // expected-note@-2 {{property access is 'async'}} - _ = await other.synchronous() // expected-warning{{non-sendable type 'NotConcurrent?' returned by implicitly async call to actor-isolated function cannot cross actor boundary}} + _ = await other.synchronous() // expected-warning{{non-sendable result type 'NotConcurrent?' cannot be sent from actor-isolated context in call to instance method 'synchronous()'}} _ = await other.asynchronous(nil) } } @@ -182,10 +182,10 @@ func globalTestMain(nc: NotConcurrent) async { // expected-tns-note @-1 {{sending global actor 'SomeGlobalActor'-isolated 'a' to global actor 'SomeGlobalActor'-isolated global function 'globalAsync' risks causing data races between global actor 'SomeGlobalActor'-isolated and local main actor-isolated uses}} await globalSync(a) // expected-tns-note {{access can happen concurrently}} _ = await ClassWithGlobalActorInits(nc) - // expected-warning @-1 {{non-sendable type 'ClassWithGlobalActorInits' returned by implicitly async call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}} + // expected-warning @-1 {{non-sendable result type 'ClassWithGlobalActorInits' cannot be sent from global actor 'SomeGlobalActor'-isolated context in call to initializer 'init(_:)'}} // expected-tns-warning @-2 {{sending 'nc' risks causing data races}} // expected-tns-note @-3 {{sending main actor-isolated 'nc' to global actor 'SomeGlobalActor'-isolated initializer 'init(_:)' risks causing data races between global actor 'SomeGlobalActor'-isolated and main actor-isolated uses}} - _ = await ClassWithGlobalActorInits() // expected-warning{{non-sendable type 'ClassWithGlobalActorInits' returned by implicitly async call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}} + _ = await ClassWithGlobalActorInits() // expected-warning{{non-sendable result type 'ClassWithGlobalActorInits' cannot be sent from global actor 'SomeGlobalActor'-isolated context in call to initializer 'init()'}} } @SomeGlobalActor diff --git a/test/Concurrency/sendable_checking.swift b/test/Concurrency/sendable_checking.swift index a063c215f36c6..bb39ca6f1203b 100644 --- a/test/Concurrency/sendable_checking.swift +++ b/test/Concurrency/sendable_checking.swift @@ -96,7 +96,7 @@ public actor MyActor: MyProto { 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 call to nonisolated function cannot cross actor boundary}} + _ = await nonisolatedAsyncFunc2() // expected-warning{{non-sendable result type 'NS1' cannot be sent from nonisolated context in call to global function 'nonisolatedAsyncFunc2()'}} } } diff --git a/test/Concurrency/sendable_conformance_checking.swift b/test/Concurrency/sendable_conformance_checking.swift index a28c03ab85ad3..8f1fa2a4112a2 100644 --- a/test/Concurrency/sendable_conformance_checking.swift +++ b/test/Concurrency/sendable_conformance_checking.swift @@ -38,7 +38,7 @@ actor A2: IsolatedWithNotSendableRequirements { nonisolated var prop: NotSendable { NotSendable() } nonisolated func fAsync() async -> NotSendable { NotSendable() } - // expected-warning@-1{{non-sendable type 'NotSendable' returned by nonisolated instance method 'fAsync()' satisfying protocol requirement cannot cross actor boundary}} + // expected-warning@-1{{non-sendable type 'NotSendable' cannot be returned from nonisolated implementation to caller of protocol requirement 'fAsync()'}} } @available(SwiftStdlib 5.1, *) @@ -51,7 +51,7 @@ protocol AsyncProtocolWithNotSendable { // actor's domain. @available(SwiftStdlib 5.1, *) actor A3: AsyncProtocolWithNotSendable { - func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying protocol requirement cannot cross actor boundary}} + func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} get async { @@ -64,7 +64,7 @@ actor A3: AsyncProtocolWithNotSendable { // actor's domain. @available(SwiftStdlib 5.1, *) actor A4: AsyncProtocolWithNotSendable { - func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying protocol requirement cannot cross actor boundary}} + func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} get { @@ -109,7 +109,7 @@ protocol AsyncThrowingProtocolWithNotSendable { // actor's domain. @available(SwiftStdlib 5.1, *) actor A7: AsyncThrowingProtocolWithNotSendable { - func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying protocol requirement cannot cross actor boundary}} + func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} get async { @@ -122,7 +122,7 @@ actor A7: AsyncThrowingProtocolWithNotSendable { // actor's domain. @available(SwiftStdlib 5.1, *) actor A8: AsyncThrowingProtocolWithNotSendable { - func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying protocol requirement cannot cross actor boundary}} + func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} get { diff --git a/test/Concurrency/transfernonsendable_asynclet.swift b/test/Concurrency/transfernonsendable_asynclet.swift index b945fcb632649..d5717b35753dc 100644 --- a/test/Concurrency/transfernonsendable_asynclet.swift +++ b/test/Concurrency/transfernonsendable_asynclet.swift @@ -722,7 +722,7 @@ func asyncLetWithoutCapture() async { // // NOTE: Error below will go away in next commit. async let x: NonSendableKlass = await returnValueFromMain() - // expected-warning @-1 {{non-sendable type 'NonSendableKlass' returned by call to main actor-isolated function cannot cross actor boundary}} + // expected-warning @-1 {{non-sendable result type 'NonSendableKlass' cannot be sent from main actor-isolated context in call to global function 'returnValueFromMain()'}} let y = await x await transferToMain(y) // expected-warning {{sending 'y' risks causing data races}} // expected-note @-1 {{sending 'y' to main actor-isolated global function 'transferToMain' risks causing data races between main actor-isolated and local nonisolated uses}} @@ -774,7 +774,7 @@ extension NonSendableStruct { async let subTask6: NonSendableStruct = self // expected-warning @-1 {{sending 'self' risks causing data races}} // expected-note @-2 {{sending 'actor'-isolated 'self' into async let risks causing data races between nonisolated and 'actor'-isolated uses}} - // expected-warning @-3 {{non-sendable type 'NonSendableStruct' returned by call to nonisolated function cannot cross actor boundary}} + // expected-warning @-3 {{non-sendable result type 'NonSendableStruct' cannot be sent from nonisolated context in call to async function}} _ = await subTask6 } } diff --git a/test/Concurrency/transfernonsendable_defer_and_typecheck_only.swift b/test/Concurrency/transfernonsendable_defer_and_typecheck_only.swift index 648f73e904ad8..6e87d68e0843b 100644 --- a/test/Concurrency/transfernonsendable_defer_and_typecheck_only.swift +++ b/test/Concurrency/transfernonsendable_defer_and_typecheck_only.swift @@ -34,7 +34,7 @@ func callActorFuncsFromNonisolated(a : A, ns : NonSendable) async { //deferred-warning@-1{{passing argument of non-sendable type 'NonSendable' into actor-isolated context may introduce data races}} _ = await a.actorRetsNS() - //expected-warning@-1{{non-sendable type 'NonSendable' returned by call to actor-isolated function cannot cross actor boundary}} + //expected-warning@-1{{non-sendable result type 'NonSendable' cannot be sent from actor-isolated context in call to instance method 'actorRetsNS()'}} } @available(SwiftStdlib 5.1, *) @@ -52,7 +52,7 @@ actor A { //deferred-warning@-1{{passing argument of non-sendable type 'NonSendable' outside of actor-isolated context may introduce data races}} _ = await retsNS() - //expected-warning@-1{{non-sendable type 'NonSendable' returned by call to nonisolated function cannot cross actor boundary}} + //expected-warning@-1{{non-sendable result type 'NonSendable' cannot be sent from nonisolated context in call to global function 'retsNS()'}} } func callActorFuncsFromDiffActor(ns : NonSendable, a : A) async { @@ -62,6 +62,6 @@ actor A { //deferred-warning@-1{{passing argument of non-sendable type 'NonSendable' into actor-isolated context may introduce data races}} _ = await a.actorRetsNS() - //expected-warning@-1{{non-sendable type 'NonSendable' returned by call to actor-isolated function cannot cross actor boundary}} + //expected-warning@-1{{non-sendable result type 'NonSendable' cannot be sent from actor-isolated context in call to instance method 'actorRetsNS()'}} } } diff --git a/test/Concurrency/transfernonsendable_sending_results.swift b/test/Concurrency/transfernonsendable_sending_results.swift index 0b1b139f4f4a0..bfa34c444edbb 100644 --- a/test/Concurrency/transfernonsendable_sending_results.swift +++ b/test/Concurrency/transfernonsendable_sending_results.swift @@ -234,7 +234,7 @@ func asyncLetReabstractionThunkTest() async { func asyncLetReabstractionThunkTest2() async { // We emit the error here since we are returning a main actor isolated value. async let newValue: NonSendableKlass = await getMainActorValueAsync() - // expected-warning @-1 {{non-sendable type 'NonSendableKlass' returned by call to main actor-isolated function cannot cross actor boundary}} + // expected-warning @-1 {{non-sendable result type 'NonSendableKlass' cannot be sent from main actor-isolated context in call to global function 'getMainActorValueAsync()'}} let _ = await newValue @@ -257,7 +257,7 @@ func asyncLetReabstractionThunkTest2() async { @MainActor func asyncLetReabstractionThunkTestGlobalActor2() async { // We emit the error here since we are returning a main actor isolated value. async let newValue: NonSendableKlass = await getMainActorValueAsync() - // expected-warning @-1 {{non-sendable type 'NonSendableKlass' returned by call to main actor-isolated function cannot cross actor boundary}} + // expected-warning @-1 {{non-sendable result type 'NonSendableKlass' cannot be sent from main actor-isolated context in call to global function 'getMainActorValueAsync()'}} let _ = await newValue From 9f0b2ec7460d659abe6a46e1db32b3836e27f6ca Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 5 Aug 2024 10:05:08 -0700 Subject: [PATCH 3/5] [Concurrency] Minor wording change to witness and override Sendable diagnostics. --- include/swift/AST/DiagnosticsSema.def | 8 ++++---- test/Concurrency/concurrent_value_checking.swift | 4 ++-- test/Concurrency/sendable_checking.swift | 12 ++++++------ test/Concurrency/sendable_override_checking.swift | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index f65526f6b7fd0..12abc3e03688e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5644,12 +5644,12 @@ ERROR(non_sendable_arg_exits_actor,none, "%kind1", (Type, const ValueDecl *, ActorIsolation)) ERROR(non_sendable_param_in_witness,none, - "non-sendable parameter type %0 cannot be sent from protocol " - "requirement %1 into %2 implementation", + "non-sendable parameter type %0 cannot be sent from caller of " + "protocol requirement %1 into %2 implementation", (Type, const ValueDecl *, ActorIsolation)) ERROR(non_sendable_param_in_override,none, - "non-sendable parameter type %0 cannot be sent from superclass " - "%kind1 into %2 override", + "non-sendable parameter type %0 cannot be sent from caller of " + "superclass %kind1 into %2 override", (Type, const ValueDecl *, ActorIsolation)) ERROR(non_sendable_param_in_objc,none, "non-sendable parameter type %0 of %2 '@objc' %kind1 cannot cross actor " diff --git a/test/Concurrency/concurrent_value_checking.swift b/test/Concurrency/concurrent_value_checking.swift index 7317d815d1927..61c9f36b1ef6a 100644 --- a/test/Concurrency/concurrent_value_checking.swift +++ b/test/Concurrency/concurrent_value_checking.swift @@ -270,7 +270,7 @@ protocol AsyncProto { } extension A1: AsyncProto { - func asyncMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable parameter type 'NotConcurrent' cannot be sent from protocol requirement 'asyncMethod' into actor-isolated implementation}} + func asyncMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable parameter type 'NotConcurrent' cannot be sent from caller of protocol requirement 'asyncMethod' into actor-isolated implementation}} } protocol MainActorProto { @@ -279,7 +279,7 @@ protocol MainActorProto { class SomeClass: MainActorProto { @SomeGlobalActor - func asyncMainMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable parameter type 'NotConcurrent' cannot be sent from protocol requirement 'asyncMainMethod' into global actor 'SomeGlobalActor'-isolated implementation}} + func asyncMainMethod(_: NotConcurrent) async { } // expected-warning{{non-sendable parameter type 'NotConcurrent' cannot be sent from caller of protocol requirement 'asyncMainMethod' into global actor 'SomeGlobalActor'-isolated implementation}} } // ---------------------------------------------------------------------- diff --git a/test/Concurrency/sendable_checking.swift b/test/Concurrency/sendable_checking.swift index bb39ca6f1203b..d75226b36f1fa 100644 --- a/test/Concurrency/sendable_checking.swift +++ b/test/Concurrency/sendable_checking.swift @@ -142,12 +142,12 @@ protocol P { func foo(x : () -> ()) -> () {} func bar(x : () -> ()) -> () {} - // expected-warning@-1 {{non-sendable parameter type '() -> ()' cannot be sent from protocol requirement 'bar(x:)' into actor-isolated implementation}} + // expected-warning@-1 {{non-sendable parameter type '() -> ()' cannot be sent from caller of protocol requirement 'bar(x:)' into actor-isolated implementation}} func foo2(x : T) -> () {} func bar2(x : T) -> () {} - // expected-warning@-1 {{non-sendable parameter type 'T' cannot be sent from protocol requirement 'bar2(x:)' into actor-isolated implementation}} + // expected-warning@-1 {{non-sendable parameter type 'T' cannot be sent from caller of protocol requirement 'bar2(x:)' into actor-isolated implementation}} } @available(SwiftStdlib 5.1, *) @@ -174,12 +174,12 @@ class Sub : Super { override nonisolated func foo(x : () -> ()) async {} override nonisolated func bar(x : () -> ()) async {} - // expected-warning@-1 {{non-sendable parameter type '() -> ()' cannot be sent from superclass instance method 'bar(x:)' into nonisolated override}} + // expected-warning@-1 {{non-sendable parameter type '() -> ()' cannot be sent from caller of superclass instance method 'bar(x:)' into nonisolated override}} override nonisolated func foo2(x: T) async {} override nonisolated func bar2(x: T) async {} - // expected-warning@-1 {{non-sendable parameter type 'T' cannot be sent from superclass instance method 'bar2(x:)' into nonisolated override}} + // expected-warning@-1 {{non-sendable parameter type 'T' cannot be sent from caller of superclass instance method 'bar2(x:)' into nonisolated override}} } @available(SwiftStdlib 5.1, *) @@ -216,8 +216,8 @@ class SuperWUnsafeSubscript { class SubWUnsafeSubscript : SuperWUnsafeSubscript { override nonisolated subscript(x : T) -> Int { get async { - // expected-warning@-2{{non-sendable parameter type 'T' cannot be sent from superclass subscript 'subscript(_:)' into nonisolated override}} - // expected-warning@-2{{non-sendable parameter type 'T' cannot be sent from superclass getter for subscript 'subscript(_:)' into nonisolated override}} + // expected-warning@-2{{non-sendable parameter type 'T' cannot be sent from caller of superclass subscript 'subscript(_:)' into nonisolated override}} + // expected-warning@-2{{non-sendable parameter type 'T' cannot be sent from caller of superclass getter for subscript 'subscript(_:)' into nonisolated override}} // there really shouldn't be two warnings produced here, see rdar://110846040 (Sendable diagnostics reported twice for subscript getters) return 0 } diff --git a/test/Concurrency/sendable_override_checking.swift b/test/Concurrency/sendable_override_checking.swift index d89f5d9ea1272..95b2e70ee6234 100644 --- a/test/Concurrency/sendable_override_checking.swift +++ b/test/Concurrency/sendable_override_checking.swift @@ -24,10 +24,10 @@ class Super { @available(SwiftStdlib 5.1, *) class Sub: Super { @MainActor override func f(_: NotSendable) async { } - // expected-warning@-1{{non-sendable parameter type 'NotSendable' cannot be sent from superclass instance method 'f' into main actor-isolated override}} + // expected-warning@-1{{non-sendable parameter type 'NotSendable' cannot be sent from caller of superclass instance method 'f' into main actor-isolated override}} nonisolated override func g1(_: NotSendable) { } // okay, synchronous nonisolated override func g2(_: NotSendable) async { } - // expected-warning@-1{{non-sendable parameter type 'NotSendable' cannot be sent from superclass instance method 'g2' into nonisolated override}} + // expected-warning@-1{{non-sendable parameter type 'NotSendable' cannot be sent from caller of superclass instance method 'g2' into nonisolated override}} } From 976d92143c4bc9e40a21afb8f742ba533e17a357 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 5 Aug 2024 14:56:45 -0700 Subject: [PATCH 4/5] [Concurrency] Split up the non-Sendable property diagnostics and improve wording. --- include/swift/AST/DiagnosticsSema.def | 31 +++++++++++++------ lib/Sema/TypeCheckConcurrency.cpp | 29 ++++++++++++++--- .../actor_call_implicitly_async.swift | 8 ++--- test/Concurrency/actor_isolation.swift | 20 ++++++------ .../concurrent_value_checking.swift | 12 +++---- test/Concurrency/sendable_checking.swift | 2 +- .../sendable_conformance_checking.swift | 8 ++--- test/Concurrency/transfernonsendable.swift | 8 ++--- 8 files changed, 74 insertions(+), 44 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 12abc3e03688e..159c6c7bb5330 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5681,16 +5681,27 @@ ERROR(non_sendable_call_result_type,none, "non-sendable result type %0 cannot be sent from %1 context in call " "to async function", (Type, ActorIsolation)) -ERROR(non_sendable_property_type,none, - "non-sendable type %0 in %select{" - "%select{asynchronous access to %4 %kind1|" - "asynchronous access from %4 context to nonisolated %kind1|" - "implicitly asynchronous access to %4 %kind1|" - "conformance of %4 %kind1 to protocol requirement|" - "%4 overriding %kind1|" - "%4 '@objc' %kind1}3|captured local %1}2 cannot " - "cross %select{actor|task}2 boundary", - (Type, const ValueDecl *, bool, unsigned, ActorIsolation)) + +ERROR(non_sendable_property_exits_actor,none, + "non-sendable type %0 of %kind1 cannot exit %2 context", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_property_into_actor,none, + "non-sendable type %0 of nonisolated %kind1 cannot be sent to " + "%2 context", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_property_in_witness,none, + "non-sendable type %0 cannot be returned from %2 implementation " + "to caller of protocol requirement %1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_property_in_override,none, + "non-sendable type %0 cannot be returned from %2 override to " + "caller of superclass %kind1", + (Type, const ValueDecl *, ActorIsolation)) +ERROR(non_sendable_property_in_objc,none, + "non-sendable type %0 returned by %2 '@objc' %kind1 cannot cross " + "actor boundary", + (Type, const ValueDecl *, ActorIsolation)) + ERROR(non_sendable_keypath_capture,none, "cannot form key path that captures non-sendable type %0", (Type)) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index f22164437ae22..1828f0527a81a 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1165,6 +1165,28 @@ getSendableResultDiag(SendableCheckReason refKind) { } } +static +Diag +getSendablePropertyDiag(SendableCheckReason refKind) { + switch (refKind) { + case SendableCheckReason::CrossActor: + case SendableCheckReason::SynchronousAsAsync: + return diag::non_sendable_property_exits_actor; + + case SendableCheckReason::ExitingActor: + return diag::non_sendable_property_into_actor; + + case SendableCheckReason::Conformance: + return diag::non_sendable_property_in_witness; + + case SendableCheckReason::Override: + return diag::non_sendable_property_in_override; + + case SendableCheckReason::ObjC: + return diag::non_sendable_property_in_objc; + } +} + bool swift::diagnoseNonSendableTypesInReference( Expr *base, ConcreteDeclRef declRef, const DeclContext *fromDC, SourceLoc refLoc, SendableCheckReason refKind, @@ -1245,11 +1267,8 @@ bool swift::diagnoseNonSendableTypesInReference( if (diagnoseNonSendableTypes( propertyType, fromDC, derivedConformanceType, refLoc, - diag::non_sendable_property_type, - var, - var->isLocalCapture(), - (unsigned)refKind, - getActorIsolation())) + getSendablePropertyDiag(refKind), + var, getActorIsolation())) return true; } diff --git a/test/Concurrency/actor_call_implicitly_async.swift b/test/Concurrency/actor_call_implicitly_async.swift index 8feebc0682ffc..85a236743c4c9 100644 --- a/test/Concurrency/actor_call_implicitly_async.swift +++ b/test/Concurrency/actor_call_implicitly_async.swift @@ -176,11 +176,11 @@ func someAsyncFunc() async { //////////// // effectful properties from outside the actor instance - // expected-warning@+2 {{non-sendable type 'Box' in asynchronous access to actor-isolated property 'effPropA' cannot cross actor boundary}} + // expected-warning@+2 {{non-sendable type 'Box' of property 'effPropA' cannot exit actor-isolated context}} // expected-error@+1{{expression is 'async' but is not marked with 'await'}} {{7-7=await }} expected-note@+1{{property access is 'async'}} _ = a.effPropA - // expected-warning@+3 {{non-sendable type 'Box' in implicitly asynchronous access to actor-isolated property 'effPropT' cannot cross actor boundary}} + // expected-warning@+3 {{non-sendable type 'Box' of property 'effPropT' cannot exit actor-isolated context}} // expected-error@+2{{property access can throw, but it is not marked with 'try' and the error is not handled}} // expected-error@+1{{expression is 'async' but is not marked with 'await'}} {{7-7=await }} expected-note@+1{{property access is 'async'}} _ = a.effPropT @@ -190,8 +190,8 @@ func someAsyncFunc() async { _ = a.effPropAT // (mostly) corrected ones - _ = await a.effPropA // expected-warning {{non-sendable type 'Box' in asynchronous access to actor-isolated property 'effPropA' cannot cross actor boundary}} - _ = try! await a.effPropT // expected-warning {{non-sendable type 'Box' in implicitly asynchronous access to actor-isolated property 'effPropT' cannot cross actor boundary}} + _ = await a.effPropA // expected-warning {{non-sendable type 'Box' of property 'effPropA' cannot exit actor-isolated context}} + _ = try! await a.effPropT // expected-warning {{non-sendable type 'Box' of property 'effPropT' cannot exit actor-isolated context}} _ = try? await a.effPropAT print("ok!") diff --git a/test/Concurrency/actor_isolation.swift b/test/Concurrency/actor_isolation.swift index 172e53edacf67..95e231a022684 100644 --- a/test/Concurrency/actor_isolation.swift +++ b/test/Concurrency/actor_isolation.swift @@ -111,7 +111,7 @@ func checkAsyncPropertyAccess() async { act.text[0] += "hello" // expected-error{{actor-isolated property 'text' can not be mutated from a nonisolated context}} - _ = act.point // expected-warning{{non-sendable type 'Point' in implicitly asynchronous access to actor-isolated property 'point' cannot cross actor boundary}} + _ = act.point // expected-warning{{non-sendable type 'Point' of property 'point' cannot exit actor-isolated context}} // expected-warning@-1 {{expression is 'async' but is not marked with 'await'}} // expected-note@-2 {{property access is 'async'}} } @@ -151,8 +151,8 @@ func checkIsolationValueType(_ formance: InferredFromConformance, _ ext: InferredFromContext, _ anno: NoGlobalActorValueType) async { // these still do need an await in Swift 5 - _ = await ext.point // expected-warning {{non-sendable type 'Point' in implicitly asynchronous access to main actor-isolated property 'point' cannot cross actor boundary}} - _ = await anno.point // expected-warning {{non-sendable type 'Point' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated property 'point' cannot cross actor boundary}} + _ = await ext.point // expected-warning {{non-sendable type 'Point' of property 'point' cannot exit main actor-isolated context}} + _ = await anno.point // expected-warning {{non-sendable type 'Point' of property 'point' cannot exit global actor 'SomeGlobalActor'-isolated context}} // expected-warning@-1 {{non-sendable type 'NoGlobalActorValueType' cannot be sent into global actor 'SomeGlobalActor'-isolated context in call to property 'point'}} _ = formance.counter @@ -162,9 +162,9 @@ func checkIsolationValueType(_ formance: InferredFromConformance, _ = await (formance as MainCounter).counter // expected-warning {{non-sendable type 'any MainCounter' cannot be sent into main actor-isolated context in call to property 'counter'}} _ = await ext[1] _ = await formance.ticker - _ = await ext.polygon // expected-warning {{non-sendable type '[Point]' in implicitly asynchronous access to main actor-isolated property 'polygon' cannot cross actor boundary}} + _ = await ext.polygon // expected-warning {{non-sendable type '[Point]' of property 'polygon' cannot exit main actor-isolated context}} _ = await InferredFromContext.stuff - _ = await NoGlobalActorValueType.polygon // expected-warning {{non-sendable type '[Point]' in implicitly asynchronous access to main actor-isolated static property 'polygon' cannot cross actor boundary}} + _ = await NoGlobalActorValueType.polygon // expected-warning {{non-sendable type '[Point]' of static property 'polygon' cannot exit main actor-isolated context}} } // expected-warning@+2 {{memberwise initializer for 'NoGlobalActorValueType' cannot be both nonisolated and global actor 'SomeGlobalActor'-isolated; this is an error in the Swift 6 language mode}} @@ -1049,8 +1049,8 @@ func testCrossModuleLets(actor: OtherModuleActor) async { _ = actor.b // okay _ = actor.c // expected-error{{expression is 'async' but is not marked with 'await'}} // expected-note@-1{{property access is 'async'}} - // expected-warning@-2{{non-sendable type 'SomeClass' in implicitly asynchronous access to actor-isolated property 'c' cannot cross actor boundary}} - _ = await actor.c // expected-warning{{non-sendable type 'SomeClass' in implicitly asynchronous access to actor-isolated property 'c' cannot cross actor boundary}} + // expected-warning@-2{{non-sendable type 'SomeClass' of property 'c' cannot exit actor-isolated context}} + _ = await actor.c // expected-warning{{non-sendable type 'SomeClass' of property 'c' cannot exit actor-isolated context}} _ = await actor.d // okay } @@ -1085,8 +1085,8 @@ actor CrossModuleFromInitsActor { _ = actor.b // okay _ = actor.c // expected-error{{expression is 'async' but is not marked with 'await'}} // expected-note@-1{{property access is 'async'}} - // expected-warning@-2{{non-sendable type 'SomeClass' in implicitly asynchronous access to actor-isolated property 'c' cannot cross actor boundary}} - _ = await actor.c // expected-warning{{non-sendable type 'SomeClass' in implicitly asynchronous access to actor-isolated property 'c' cannot cross actor boundary}} + // expected-warning@-2{{non-sendable type 'SomeClass' of property 'c' cannot exit actor-isolated context}} + _ = await actor.c // expected-warning{{non-sendable type 'SomeClass' of property 'c' cannot exit actor-isolated context}} _ = await actor.d // okay } } @@ -1613,7 +1613,7 @@ class ReferenceActor { init() async { self.a = ProtectNonSendable() - // expected-warning@+3 {{non-sendable type 'NonSendable' in implicitly asynchronous access to actor-isolated property 'ns' cannot cross actor boundary}} + // expected-warning@+3 {{non-sendable type 'NonSendable' of property 'ns' cannot exit actor-isolated context}} // expected-warning@+2 {{expression is 'async' but is not marked with 'await'}} // expected-note@+1 {{property access is 'async'}} _ = a.ns diff --git a/test/Concurrency/concurrent_value_checking.swift b/test/Concurrency/concurrent_value_checking.swift index 61c9f36b1ef6a..b5f23998c129a 100644 --- a/test/Concurrency/concurrent_value_checking.swift +++ b/test/Concurrency/concurrent_value_checking.swift @@ -99,7 +99,7 @@ extension A1 { _ = await self.asynchronous(nil) // Across to a different actor, so Sendable restriction is enforced. - _ = other.localLet // expected-warning{{non-sendable type 'NotConcurrent' in implicitly asynchronous access to actor-isolated property 'localLet' cannot cross actor boundary}} + _ = other.localLet // expected-warning{{non-sendable type 'NotConcurrent' of property 'localLet' cannot exit actor-isolated context}} // expected-warning@-1 {{expression is 'async' but is not marked with 'await'}} // expected-note@-2 {{property access is 'async'}} _ = await other.synchronous() // expected-warning{{non-sendable result type 'NotConcurrent?' cannot be sent from actor-isolated context in call to instance method 'synchronous()'}} @@ -140,14 +140,14 @@ enum E { func globalTest() async { // expected-warning@+2 {{expression is 'async' but is not marked with 'await'}} // expected-note@+1 {{property access is 'async'}} - let a = globalValue // expected-warning{{non-sendable type 'NotConcurrent?' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated let 'globalValue' cannot cross actor boundary}} + let a = globalValue // expected-warning{{non-sendable type 'NotConcurrent?' of let 'globalValue' cannot exit global actor 'SomeGlobalActor'-isolated context}} await globalAsync(a) // expected-tns-warning {{sending 'a' risks causing data races}} // expected-tns-note @-1 {{sending global actor 'SomeGlobalActor'-isolated 'a' to global actor 'SomeGlobalActor'-isolated global function 'globalAsync' risks causing data races between global actor 'SomeGlobalActor'-isolated and local nonisolated uses}} await globalSync(a) // expected-tns-note {{access can happen concurrently}} // expected-warning@+2 {{expression is 'async' but is not marked with 'await'}} // expected-note@+1 {{property access is 'async'}} - let _ = E.notSafe // expected-warning{{non-sendable type 'NotConcurrent?' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated static property 'notSafe' cannot cross actor boundary}} + let _ = E.notSafe // expected-warning{{non-sendable type 'NotConcurrent?' of static property 'notSafe' cannot exit global actor 'SomeGlobalActor'-isolated context}} #if ALLOW_TYPECHECKER_ERRORS // expected-typechecker-error@+3 {{expression is 'async' but is not marked with 'await'}} @@ -155,7 +155,7 @@ func globalTest() async { // expected-typechecker-note@+1 {{property access is 'async'}} globalAsync(E.notSafe) - // expected-typechecker-warning@-2 {{non-sendable type 'NotConcurrent?' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated static property 'notSafe' cannot cross actor boundary}} + // expected-typechecker-warning@-2 {{non-sendable type 'NotConcurrent?' of static property 'notSafe' cannot exit global actor 'SomeGlobalActor'-isolated context}} #endif } @@ -177,7 +177,7 @@ class ClassWithGlobalActorInits { // expected-note 2{{class 'ClassWithGlobalActo func globalTestMain(nc: NotConcurrent) async { // expected-warning@+2 {{expression is 'async' but is not marked with 'await'}} // expected-note@+1 {{property access is 'async'}} - let a = globalValue // expected-warning {{non-sendable type 'NotConcurrent?' in implicitly asynchronous access to global actor 'SomeGlobalActor'-isolated let 'globalValue' cannot cross actor boundary}} + let a = globalValue // expected-warning {{non-sendable type 'NotConcurrent?' of let 'globalValue' cannot exit global actor 'SomeGlobalActor'-isolated context}} await globalAsync(a) // expected-tns-warning {{sending 'a' risks causing data races}} // expected-tns-note @-1 {{sending global actor 'SomeGlobalActor'-isolated 'a' to global actor 'SomeGlobalActor'-isolated global function 'globalAsync' risks causing data races between global actor 'SomeGlobalActor'-isolated and local main actor-isolated uses}} await globalSync(a) // expected-tns-note {{access can happen concurrently}} @@ -259,7 +259,7 @@ actor ANI { } func testANI(ani: ANI) async { - _ = ani.nc // expected-warning{{non-sendable type 'NC' in asynchronous access to nonisolated property 'nc' cannot cross actor boundary}} + _ = ani.nc // expected-warning{{non-sendable type 'NC' of property 'nc' cannot exit nonisolated context}} } // ---------------------------------------------------------------------- diff --git a/test/Concurrency/sendable_checking.swift b/test/Concurrency/sendable_checking.swift index d75226b36f1fa..1dc35df67a467 100644 --- a/test/Concurrency/sendable_checking.swift +++ b/test/Concurrency/sendable_checking.swift @@ -443,7 +443,7 @@ struct DowngradeForPreconcurrency { self.x // expected-warning@-1 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}} // expected-note@-2 {{property access is 'async'}} - // expected-warning@-3 {{non-sendable type 'NonSendable' in implicitly asynchronous access to main actor-isolated property 'x' cannot cross actor boundary; this is an error in the Swift 6 language mode}} + // expected-warning@-3 {{non-sendable type 'NonSendable' of property 'x' cannot exit main actor-isolated context; this is an error in the Swift 6 language mode}} } } } diff --git a/test/Concurrency/sendable_conformance_checking.swift b/test/Concurrency/sendable_conformance_checking.swift index 8f1fa2a4112a2..3eeafdff72176 100644 --- a/test/Concurrency/sendable_conformance_checking.swift +++ b/test/Concurrency/sendable_conformance_checking.swift @@ -53,7 +53,7 @@ protocol AsyncProtocolWithNotSendable { actor A3: AsyncProtocolWithNotSendable { func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} - var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} + var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'prop'}} get async { NotSendable() } @@ -66,7 +66,7 @@ actor A3: AsyncProtocolWithNotSendable { actor A4: AsyncProtocolWithNotSendable { func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} - var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} + var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'prop'}} get { NotSendable() } @@ -111,7 +111,7 @@ protocol AsyncThrowingProtocolWithNotSendable { actor A7: AsyncThrowingProtocolWithNotSendable { func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} - var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} + var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'prop'}} get async { NotSendable() } @@ -124,7 +124,7 @@ actor A7: AsyncThrowingProtocolWithNotSendable { actor A8: AsyncThrowingProtocolWithNotSendable { func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'f()'}} - var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to protocol requirement cannot cross actor boundary}} + var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' cannot be returned from actor-isolated implementation to caller of protocol requirement 'prop'}} get { NotSendable() } diff --git a/test/Concurrency/transfernonsendable.swift b/test/Concurrency/transfernonsendable.swift index 36ff5b28dcc2b..cc0cd1d8fd2d1 100644 --- a/test/Concurrency/transfernonsendable.swift +++ b/test/Concurrency/transfernonsendable.swift @@ -1474,8 +1474,8 @@ actor ActorWithSetter { func recursive() async { let x = NonSendableKlass() await self.recursive!.twoFieldBoxInTuple.1.k2 = x - // expected-typechecker-only-warning @-1 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' in implicitly asynchronous access to actor-isolated property 'twoFieldBoxInTuple' cannot cross actor boundary}} - // expected-typechecker-only-warning @-2 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' in implicitly asynchronous access to actor-isolated property 'twoFieldBoxInTuple' cannot cross actor boundary}} + // expected-typechecker-only-warning @-1 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' of property 'twoFieldBoxInTuple' cannot exit actor-isolated context}} + // expected-typechecker-only-warning @-2 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' of property 'twoFieldBoxInTuple' cannot exit actor-isolated context}} await transferToMain(x) // xpected-tns-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}} // expected-complete-warning @-1 {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} @@ -1527,8 +1527,8 @@ final actor FinalActorWithSetter { func recursive() async { let x = NonSendableKlass() await self.recursive!.twoFieldBoxInTuple.1.k2 = x - // expected-typechecker-only-warning @-1 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' in implicitly asynchronous access to actor-isolated property 'twoFieldBoxInTuple' cannot cross actor boundary}} - // expected-typechecker-only-warning @-2 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' in implicitly asynchronous access to actor-isolated property 'twoFieldBoxInTuple' cannot cross actor boundary}} + // expected-typechecker-only-warning @-1 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' of property 'twoFieldBoxInTuple' cannot exit actor-isolated context}} + // expected-typechecker-only-warning @-2 {{non-sendable type '(NonSendableKlass, TwoFieldKlassBox)' of property 'twoFieldBoxInTuple' cannot exit actor-isolated context}} await transferToMain(x) // xpected-tns-warning {{call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller}} // expected-complete-warning @-1 {{passing argument of non-sendable type 'NonSendableKlass' into main actor-isolated context may introduce data races}} From 7dbec846f78a407e4f835cba8e37e727c7a119f7 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Mon, 5 Aug 2024 16:27:41 -0700 Subject: [PATCH 5/5] [NFC] Update a few tests for concurrency diagnostics changes. --- test/Sema/moveonly_sendable.swift | 2 +- validation-test/Sema/SwiftUI/rdar76252310.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Sema/moveonly_sendable.swift b/test/Sema/moveonly_sendable.swift index e9d590dd006a9..14ddb32280ecb 100644 --- a/test/Sema/moveonly_sendable.swift +++ b/test/Sema/moveonly_sendable.swift @@ -48,7 +48,7 @@ func processFiles(_ a: A, _ anotherFile: borrowing FileDescriptor) async { await a.takeMaybeFile(.available(anotherFile)) _ = A(.available(anotherFile)) - let ns = await a.getRef() // expected-warning {{non-sendable type 'NotSendableMO' returned by implicitly async call to actor-isolated function cannot cross actor boundary}} + let ns = await a.getRef() // expected-warning {{non-sendable result type 'NotSendableMO' cannot be sent from actor-isolated context in call to instance method 'getRef()'}} await takeNotSendable(ns) // expected-complete-warning {{passing argument of non-sendable type 'NotSendableMO' outside of main actor-isolated context may introduce data races}} switch (await a.giveFileDescriptor()) { diff --git a/validation-test/Sema/SwiftUI/rdar76252310.swift b/validation-test/Sema/SwiftUI/rdar76252310.swift index 0b84ed4f7f563..397bca36bf613 100644 --- a/validation-test/Sema/SwiftUI/rdar76252310.swift +++ b/validation-test/Sema/SwiftUI/rdar76252310.swift @@ -42,7 +42,7 @@ func fromConcurrencyAware() async { let view = CoffeeTrackerView() // synthesized 'init' is 'nonisolated' // expected-note@+3 {{property access is 'async'}} - // expected-warning@+2 {{non-sendable type 'some View' in implicitly asynchronous access to main actor-isolated property 'body' cannot cross actor boundary}} + // expected-warning@+2 {{non-sendable type 'some View' of property 'body' cannot exit main actor-isolated context}} // expected-warning@+1 {{expression is 'async' but is not marked with 'await'}} _ = view.body