Skip to content

Commit 61b22f8

Browse files
committed
[Actor isolation] Limit propagation of unsafe global actors to instance members
Don't propagate implicit, unsafe global actor annotations from a type to its instance members. We want the annotation to cover all of a type, but not implicitly cover (e.g.) all of its subclasses's members except those it gets through overrides or witnessing protocol requirements.
1 parent 9d8fde8 commit 61b22f8

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,8 +2666,16 @@ ActorIsolation ActorIsolationRequest::evaluate(
26662666
// If the declaration is in a nominal type (or extension thereof) that
26672667
// has isolation, use that.
26682668
if (auto selfTypeDecl = value->getDeclContext()->getSelfNominalTypeDecl()) {
2669-
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl))
2670-
return inferredIsolation(selfTypeIsolation);
2669+
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl)) {
2670+
// Don't propagate implicit, unsafe global actor isolation from a type
2671+
// to non-imported instance members.
2672+
if (selfTypeIsolation != ActorIsolation::GlobalActorUnsafe ||
2673+
value->getClangNode() ||
2674+
(selfTypeDecl->getGlobalActorAttr() &&
2675+
!selfTypeDecl->getGlobalActorAttr()->first->isImplicit())) {
2676+
return inferredIsolation(selfTypeIsolation);
2677+
}
2678+
}
26712679
}
26722680
}
26732681

test/ClangImporter/objc_async.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import Foundation
66
import ObjCConcurrency
77

8-
@MainActor func onlyOnMainActor() { }
8+
@MainActor func onlyOnMainActor() { } // expected-note{{calls to global function 'onlyOnMainActor()' from outside of its actor context are implicitly asynchronous}}
99

1010
func testSlowServer(slowServer: SlowServer) async throws {
1111
let _: Int = await slowServer.doSomethingSlow("mail")
@@ -130,6 +130,8 @@ struct SomeGlobalActor {
130130
static let shared = SomeActor()
131131
}
132132

133+
@SomeGlobalActor(unsafe) func unsafelyOnSomeGlobal() { }
134+
133135
class MyButton : NXButton {
134136
@MainActor func testMain() {
135137
onButtonPress() // okay
@@ -139,11 +141,29 @@ class MyButton : NXButton {
139141
onButtonPress() // expected-error{{instance method 'onButtonPress()' isolated to global actor 'MainActor' can not be referenced from different global actor 'SomeGlobalActor'}}
140142
}
141143

144+
func test() { // expected-note{{add '@MainActor' to make instance method 'test()' part of global actor 'MainActor'}}
145+
onButtonPress() // okay, onButtonPress is @MainActor(unsafe)
146+
unsafelyOnSomeGlobal() // okay, we haven't opted into anything
147+
onlyOnMainActor() // expected-error{{global function 'onlyOnMainActor()' isolated to global actor 'MainActor' can not be referenced from this synchronous context}}
148+
}
149+
}
150+
151+
class MyOtherButton: NXButton {
152+
override func onButtonPress() { // expected-note{{calls to instance method 'onButtonPress()' from outside of its actor context are implicitly asynchronous}}
153+
onlyOnMainActor() // yes, we're on the main actor
154+
unsafelyOnSomeGlobal() // okay, we haven't opted into any actual checking
155+
}
156+
142157
func test() {
143-
onButtonPress() // okay
158+
onButtonPress() // okay, it's @MainActor(unsafe)
159+
}
160+
161+
@SomeGlobalActor func testOther() {
162+
onButtonPress() // expected-error{{instance method 'onButtonPress()' isolated to global actor 'MainActor' can not be referenced from different global actor 'SomeGlobalActor' in a synchronous context}}
144163
}
145164
}
146165

166+
147167
func testButtons(mb: MyButton) {
148168
mb.onButtonPress()
149169
}

0 commit comments

Comments
 (0)