Skip to content

Commit db78455

Browse files
committed
[Concurrency] Start diagnosing use of global actor isolated properties in key paths
If key path is formed in a concurrency domain different from the one where the member is, diagnose that as a warning until Swift 6.
1 parent b8d5e4c commit db78455

File tree

3 files changed

+68
-17
lines changed

3 files changed

+68
-17
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3343,8 +3343,8 @@ namespace {
33433343
for (const auto &component : keyPath->getComponents()) {
33443344
// The decl referred to by the path component cannot be within an actor.
33453345
if (component.hasDeclRef()) {
3346-
auto concDecl = component.getDeclRef();
3347-
auto decl = concDecl.getDecl();
3346+
auto declRef = component.getDeclRef();
3347+
auto decl = declRef.getDecl();
33483348
auto isolation = getActorIsolationForReference(
33493349
decl, getDeclContext());
33503350
switch (isolation) {
@@ -3354,13 +3354,16 @@ namespace {
33543354
break;
33553355

33563356
case ActorIsolation::GlobalActor:
3357-
case ActorIsolation::GlobalActorUnsafe:
3358-
// Disable global actor checking for now.
3359-
if (isolation.isGlobalActor() &&
3360-
!ctx.LangOpts.isSwiftVersionAtLeast(6))
3357+
case ActorIsolation::GlobalActorUnsafe: {
3358+
auto result = ActorReferenceResult::forReference(
3359+
declRef, component.getLoc(), getDeclContext(),
3360+
kindOfUsage(decl, keyPath));
3361+
3362+
if (result == ActorReferenceResult::SameConcurrencyDomain)
33613363
break;
33623364

33633365
LLVM_FALLTHROUGH;
3366+
}
33643367

33653368
case ActorIsolation::ActorInstance:
33663369
// If this entity is always accessible across actors, just check
@@ -3376,11 +3379,17 @@ namespace {
33763379
break;
33773380
}
33783381

3379-
ctx.Diags.diagnose(component.getLoc(),
3380-
diag::actor_isolated_keypath_component,
3381-
isolation.isDistributedActor(),
3382-
decl);
3383-
diagnosed = true;
3382+
{
3383+
auto diagnostic = ctx.Diags.diagnose(
3384+
component.getLoc(), diag::actor_isolated_keypath_component,
3385+
isolation.isDistributedActor(), decl);
3386+
3387+
if (isolation == ActorIsolation::ActorInstance)
3388+
diagnosed = true;
3389+
else
3390+
diagnostic.warnUntilSwiftVersion(6);
3391+
}
3392+
33843393
break;
33853394
}
33863395
}

test/Concurrency/actor_keypath_isolation.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func tryKeyPathsMisc(d : Door) {
5858

5959
func tryKeyPathsFromAsync() async {
6060
_ = \Door.unsafeGlobActor_immutable
61-
_ = \Door.unsafeGlobActor_mutable // okay for now
61+
_ = \Door.unsafeGlobActor_mutable // expected-warning {{cannot form key path to actor-isolated property 'unsafeGlobActor_mutable'; this is an error in Swift 6}}
6262
}
6363

6464
func tryNonSendable() {
@@ -69,7 +69,7 @@ func tryNonSendable() {
6969

7070
func tryKeypaths() {
7171
_ = \Door.unsafeGlobActor_immutable
72-
_ = \Door.unsafeGlobActor_mutable // okay for now
72+
_ = \Door.unsafeGlobActor_mutable // expected-warning {{cannot form key path to actor-isolated property 'unsafeGlobActor_mutable'; this is an error in Swift 6}}
7373

7474
_ = \Door.immutable
7575
_ = \Door.globActor_immutable
@@ -84,7 +84,7 @@ func tryKeypaths() {
8484
let _ : PartialKeyPath<Door> = \.mutable // expected-error{{cannot form key path to actor-isolated property 'mutable'}}
8585
let _ : AnyKeyPath = \Door.mutable // expected-error{{cannot form key path to actor-isolated property 'mutable'}}
8686

87-
_ = \Door.globActor_mutable // okay for now
87+
_ = \Door.globActor_mutable // expected-warning {{cannot form key path to actor-isolated property 'globActor_mutable'; this is an error in Swift 6}}
8888
_ = \Door.[0] // expected-error{{cannot form key path to actor-isolated subscript 'subscript(_:)'}}
89-
_ = \Door.["hello"] // okay for now
89+
_ = \Door.["hello"] // expected-warning {{cannot form key path to actor-isolated subscript 'subscript(_:)'; this is an error in Swift 6}}
9090
}

test/Concurrency/sendable_keypaths.swift

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-feature InferSendableFromCaptures -strict-concurrency=complete
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature InferSendableFromCaptures -strict-concurrency=complete
22

33
// REQUIRES: concurrency
44
// REQUIRES: asserts
55

6+
actor SomeActor {
7+
}
8+
9+
@globalActor
10+
actor GlobalActor {
11+
static let shared: SomeActor = SomeActor()
12+
}
13+
614
class NonSendable : Hashable {
715
var data: Int
816

@@ -140,17 +148,51 @@ do {
140148
}
141149

142150
// Global actor isolated properties.
143-
do {
151+
func testGlobalActorIsolatedReferences() {
144152
@MainActor struct Isolated {
145153
var data: Int = 42
146154
subscript(v: Int) -> Bool { false }
147155
}
148156

149157
let dataKP = \Isolated.data
158+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'data'; this is an error in Swift 6}}
150159
let subscriptKP = \Isolated.[42]
160+
// expected-warning@-1 {{cannot form key path to actor-isolated subscript 'subscript(_:)'; this is an error in Swift 6}}
151161

152162
let _: KeyPath<Isolated, Int> & Sendable = dataKP
153163
// expected-warning@-1 {{type 'WritableKeyPath<Isolated, Int>' does not conform to the 'Sendable' protocol}}
154164
let _: KeyPath<Isolated, Bool> & Sendable = subscriptKP
155165
// expected-warning@-1 {{type 'KeyPath<Isolated, Bool>' does not conform to the 'Sendable' protocol}}
166+
167+
func testNonIsolated() {
168+
_ = \Isolated.data
169+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'data'; this is an error in Swift 6}}
170+
}
171+
172+
@MainActor func testIsolated() {
173+
_ = \Isolated.data // Ok
174+
}
175+
}
176+
177+
func testReferencesToDifferentGlobalActorIsolatedMembers() {
178+
struct Info {
179+
@MainActor var name: String { "" }
180+
}
181+
182+
struct Isolated {
183+
@GlobalActor var info: Info { Info() }
184+
}
185+
186+
@MainActor func testIsolatedToMain() {
187+
_ = \Info.name // Ok
188+
_ = \Isolated.info.name
189+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'info'; this is an error in Swift 6}}
190+
}
191+
192+
@GlobalActor func testIsolatedToCustom() {
193+
_ = \Info.name // Ok
194+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'name'; this is an error in Swift 6}}
195+
_ = \Isolated.info.name
196+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'name'; this is an error in Swift 6}}
197+
}
156198
}

0 commit comments

Comments
 (0)