Skip to content

Commit 88e32e4

Browse files
committed
Improve sendable diagnostics for property accesses
1 parent 7c47803 commit 88e32e4

File tree

6 files changed

+25
-19
lines changed

6 files changed

+25
-19
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4593,9 +4593,13 @@ WARNING(non_sendable_call_result_type,none,
45934593
"call to %2 function cannot cross actor boundary",
45944594
(Type, bool, ActorIsolation))
45954595
WARNING(non_sendable_property_type,none,
4596-
"cannot use %1 %2 with a non-sendable type %0 "
4597-
"%select{across actors|from concurrently-executed code}3",
4598-
(Type, DescriptiveDeclKind, DeclName, bool))
4596+
"non-sendable type %0 in %select{"
4597+
"%select{asynchronous access to %5 %1 %2|"
4598+
"implicitly asynchronous access to %5 %1 %2|"
4599+
"conformance of %5 %1 %2 to non-isolated protocol requirement|"
4600+
"%5 '@objc' %1 %2}4|captured local %1 %2}3 cannot "
4601+
"cross %select{actor|task}3 boundary",
4602+
(Type, DescriptiveDeclKind, DeclName, bool, unsigned, ActorIsolation))
45994603
WARNING(non_sendable_keypath_capture,none,
46004604
"cannot form key path that captures non-sendable type %0",
46014605
(Type))

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,9 @@ bool swift::diagnoseNonSendableTypesInReference(
815815
propertyType, fromDC, loc,
816816
diag::non_sendable_property_type,
817817
var->getDescriptiveKind(), var->getName(),
818-
var->isLocalCapture()))
818+
var->isLocalCapture(),
819+
(unsigned)reason,
820+
getActorIsolation(var)))
819821
return true;
820822
}
821823

test/Concurrency/actor_call_implicitly_async.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ func someAsyncFunc() async {
175175
////////////
176176
// effectful properties from outside the actor instance
177177

178-
// expected-warning@+2 {{cannot use property 'effPropA' with a non-sendable type 'Box' across actors}}
178+
// expected-warning@+2 {{non-sendable type 'Box' in asynchronous access to actor-isolated property 'effPropA' cannot cross actor boundary}}
179179
// expected-error@+1{{expression is 'async' but is not marked with 'await'}} {{7-7=await }} expected-note@+1{{property access is 'async'}}
180180
_ = a.effPropA
181181

182-
// expected-warning@+3 {{cannot use property 'effPropT' with a non-sendable type 'Box' across actors}}
182+
// expected-warning@+3 {{non-sendable type 'Box' in implicitly asynchronous access to actor-isolated property 'effPropT' cannot cross actor boundary}}
183183
// expected-error@+2{{property access can throw, but it is not marked with 'try' and the error is not handled}}
184184
// expected-error@+1{{expression is 'async' but is not marked with 'await'}} {{7-7=await }} expected-note@+1{{property access is 'async'}}
185185
_ = a.effPropT
@@ -189,8 +189,8 @@ func someAsyncFunc() async {
189189
_ = a.effPropAT
190190

191191
// (mostly) corrected ones
192-
_ = await a.effPropA // expected-warning {{cannot use property 'effPropA' with a non-sendable type 'Box' across actors}}
193-
_ = try! await a.effPropT // expected-warning {{cannot use property 'effPropT' with a non-sendable type 'Box' across actors}}
192+
_ = await a.effPropA // expected-warning {{non-sendable type 'Box' in asynchronous access to actor-isolated property 'effPropA' cannot cross actor boundary}}
193+
_ = try! await a.effPropT // expected-warning {{non-sendable type 'Box' in implicitly asynchronous access to actor-isolated property 'effPropT' cannot cross actor boundary}}
194194
_ = try? await a.effPropAT
195195

196196
print("ok!")

test/Concurrency/actor_isolation.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func checkAsyncPropertyAccess() async {
106106

107107
act.text[0] += "hello" // expected-error{{actor-isolated property 'text' can not be mutated from a non-isolated context}}
108108

109-
_ = act.point // expected-warning{{cannot use property 'point' with a non-sendable type 'Point' across actors}}
109+
_ = act.point // expected-warning{{non-sendable type 'Point' in asynchronous access to actor-isolated property 'point' cannot cross actor boundary}}
110110
}
111111

112112
@available(SwiftStdlib 5.1, *)
@@ -872,8 +872,8 @@ func testCrossModuleLets(actor: OtherModuleActor) async {
872872
_ = actor.b // okay
873873
_ = actor.c // expected-error{{expression is 'async' but is not marked with 'await'}}
874874
// expected-note@-1{{property access is 'async'}}
875-
// expected-warning@-2{{cannot use property 'c' with a non-sendable type 'SomeClass' across actors}}
876-
_ = await actor.c // expected-warning{{cannot use property 'c' with a non-sendable type 'SomeClass' across actors}}
875+
// expected-warning@-2{{non-sendable type 'SomeClass' in implicitly asynchronous access to actor-isolated property 'c' cannot cross actor boundary}}
876+
_ = await actor.c // expected-warning{{non-sendable type 'SomeClass' in implicitly asynchronous access to actor-isolated property 'c' cannot cross actor boundary}}
877877
_ = await actor.d // okay
878878
}
879879

test/Concurrency/concurrent_value_checking.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ extension A1 {
5050
_ = await self.asynchronous(nil)
5151

5252
// Across to a different actor, so Sendable restriction is enforced.
53-
_ = other.localLet // expected-warning{{cannot use property 'localLet' with a non-sendable type 'NotConcurrent' across actors}}
53+
_ = other.localLet // expected-warning{{non-sendable type 'NotConcurrent' in asynchronous access to actor-isolated property 'localLet' cannot cross actor boundary}}
5454
_ = await other.synchronous() // expected-warning{{non-sendable type 'NotConcurrent?' returned by implicitly asynchronous call to actor-isolated instance method 'synchronous()' cannot cross actor boundary}}
5555
_ = await other.asynchronous(nil) // expected-warning{{non-sendable type 'NotConcurrent?' passed in call to actor-isolated instance method 'asynchronous' cannot cross actor boundary}}
5656
}
@@ -80,7 +80,7 @@ func globalAsync(_: NotConcurrent?) async {
8080
}
8181

8282
func globalTest() async {
83-
let a = globalValue // expected-warning{{cannot use let 'globalValue' with a non-sendable type 'NotConcurrent?' across actors}}
83+
let a = globalValue // expected-warning{{non-sendable type 'NotConcurrent?' in asynchronous access to global actor 'SomeGlobalActor'-isolated let 'globalValue' cannot cross actor boundary}}
8484
await globalAsync(a) // expected-warning{{non-sendable type 'NotConcurrent?' passed in implicitly asynchronous call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}}
8585
await globalSync(a) // expected-warning{{non-sendable type 'NotConcurrent?' passed in call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}}
8686
}
@@ -101,7 +101,7 @@ class ClassWithGlobalActorInits { // expected-note 2{{class 'ClassWithGlobalActo
101101

102102
@MainActor
103103
func globalTestMain(nc: NotConcurrent) async {
104-
let a = globalValue // expected-warning{{cannot use let 'globalValue' with a non-sendable type 'NotConcurrent?' across actors}}
104+
let a = globalValue // expected-warning{{non-sendable type 'NotConcurrent?' in asynchronous access to global actor 'SomeGlobalActor'-isolated let 'globalValue' cannot cross actor boundary}}
105105
await globalAsync(a) // expected-warning{{non-sendable type 'NotConcurrent?' passed in implicitly asynchronous call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}}
106106
await globalSync(a) // expected-warning{{non-sendable type 'NotConcurrent?' passed in call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}}
107107
_ = await ClassWithGlobalActorInits(nc) // expected-warning{{non-sendable type 'NotConcurrent' passed in call to global actor 'SomeGlobalActor'-isolated function cannot cross actor boundary}}
@@ -180,7 +180,7 @@ actor ANI {
180180
}
181181

182182
func testANI(ani: ANI) async {
183-
_ = ani.nc // expected-warning{{cannot use property 'nc' with a non-sendable type 'NC' across actors}}
183+
_ = ani.nc // expected-warning{{non-sendable type 'NC' in asynchronous access to nonisolated property 'nc' cannot cross actor boundary}}
184184
}
185185

186186
// ----------------------------------------------------------------------

test/Concurrency/sendable_conformance_checking.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ protocol AsyncProtocolWithNotSendable {
4242
actor A3: AsyncProtocolWithNotSendable {
4343
func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying non-isolated protocol requirement cannot cross actor boundary}}
4444

45-
var prop: NotSendable { // expected-warning{{cannot use property 'prop' with a non-sendable type 'NotSendable' across actors}}
45+
var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to non-isolated protocol requirement cannot cross actor boundary}}
4646
get async {
4747
NotSendable()
4848
}
@@ -55,7 +55,7 @@ actor A3: AsyncProtocolWithNotSendable {
5555
actor A4: AsyncProtocolWithNotSendable {
5656
func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying non-isolated protocol requirement cannot cross actor boundary}}
5757

58-
var prop: NotSendable { // expected-warning{{cannot use property 'prop' with a non-sendable type 'NotSendable' across actors}}
58+
var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to non-isolated protocol requirement cannot cross actor boundary}}
5959
get {
6060
NotSendable()
6161
}
@@ -100,7 +100,7 @@ protocol AsyncThrowingProtocolWithNotSendable {
100100
actor A7: AsyncThrowingProtocolWithNotSendable {
101101
func f() async -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying non-isolated protocol requirement cannot cross actor boundary}}
102102

103-
var prop: NotSendable { // expected-warning{{cannot use property 'prop' with a non-sendable type 'NotSendable' across actors}}
103+
var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to non-isolated protocol requirement cannot cross actor boundary}}
104104
get async {
105105
NotSendable()
106106
}
@@ -113,7 +113,7 @@ actor A7: AsyncThrowingProtocolWithNotSendable {
113113
actor A8: AsyncThrowingProtocolWithNotSendable {
114114
func f() -> NotSendable { NotSendable() } // expected-warning{{non-sendable type 'NotSendable' returned by actor-isolated instance method 'f()' satisfying non-isolated protocol requirement cannot cross actor boundary}}
115115

116-
var prop: NotSendable { // expected-warning{{cannot use property 'prop' with a non-sendable type 'NotSendable' across actors}}
116+
var prop: NotSendable { // expected-warning{{non-sendable type 'NotSendable' in conformance of actor-isolated property 'prop' to non-isolated protocol requirement cannot cross actor boundary}}
117117
get {
118118
NotSendable()
119119
}

0 commit comments

Comments
 (0)