Skip to content

Commit 9a529e9

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 9a529e9

File tree

3 files changed

+70
-16
lines changed

3 files changed

+70
-16
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: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,17 +140,62 @@ do {
140140
}
141141

142142
// Global actor isolated properties.
143-
do {
143+
func testGlobalActorIsolatedReferences() {
144144
@MainActor struct Isolated {
145145
var data: Int = 42
146146
subscript(v: Int) -> Bool { false }
147147
}
148148

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

152154
let _: KeyPath<Isolated, Int> & Sendable = dataKP
153155
// expected-warning@-1 {{type 'WritableKeyPath<Isolated, Int>' does not conform to the 'Sendable' protocol}}
154156
let _: KeyPath<Isolated, Bool> & Sendable = subscriptKP
155157
// expected-warning@-1 {{type 'KeyPath<Isolated, Bool>' does not conform to the 'Sendable' protocol}}
158+
159+
func testNonIsolated() {
160+
_ = \Isolated.data
161+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'data'; this is an error in Swift 6}}
162+
}
163+
164+
@MainActor func testIsolated() {
165+
_ = \Isolated.data // Ok
166+
}
167+
}
168+
169+
@available(SwiftStdlib 5.1, *)
170+
actor SomeActor {
171+
}
172+
173+
@available(SwiftStdlib 5.1, *)
174+
@globalActor
175+
actor GlobalActor {
176+
static let shared: SomeActor = SomeActor()
177+
}
178+
179+
@available(SwiftStdlib 5.1, *)
180+
func testReferencesToDifferentGlobalActorIsolatedMembers() {
181+
struct Info {
182+
@MainActor var name: String { "" }
183+
}
184+
185+
struct Isolated {
186+
@GlobalActor var info: Info { Info() }
187+
}
188+
189+
@MainActor func testIsolatedToMain() {
190+
_ = \Info.name // Ok
191+
_ = \Isolated.info.name
192+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'info'; this is an error in Swift 6}}
193+
}
194+
195+
@GlobalActor func testIsolatedToCustom() {
196+
_ = \Info.name // Ok
197+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'name'; this is an error in Swift 6}}
198+
_ = \Isolated.info.name
199+
// expected-warning@-1 {{cannot form key path to actor-isolated property 'name'; this is an error in Swift 6}}
200+
}
156201
}

0 commit comments

Comments
 (0)