Skip to content

Commit d0551d9

Browse files
authored
Merge pull request swiftlang#36620 from DougGregor/limit-global-actor-propagation
[Actor isolation] Limit propagation of unsafe global actors to instance members
2 parents 360e32b + 61b22f8 commit d0551d9

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
@@ -2674,8 +2674,16 @@ ActorIsolation ActorIsolationRequest::evaluate(
26742674
// If the declaration is in a nominal type (or extension thereof) that
26752675
// has isolation, use that.
26762676
if (auto selfTypeDecl = value->getDeclContext()->getSelfNominalTypeDecl()) {
2677-
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl))
2678-
return inferredIsolation(selfTypeIsolation);
2677+
if (auto selfTypeIsolation = getActorIsolation(selfTypeDecl)) {
2678+
// Don't propagate implicit, unsafe global actor isolation from a type
2679+
// to non-imported instance members.
2680+
if (selfTypeIsolation != ActorIsolation::GlobalActorUnsafe ||
2681+
value->getClangNode() ||
2682+
(selfTypeDecl->getGlobalActorAttr() &&
2683+
!selfTypeDecl->getGlobalActorAttr()->first->isImplicit())) {
2684+
return inferredIsolation(selfTypeIsolation);
2685+
}
2686+
}
26792687
}
26802688
}
26812689

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)