Skip to content

Commit 2894896

Browse files
committed
[Concurrency] Two isolation inference changes for default isolation mode.
1. Non-actor initializers should participate in custom default isolation inference. Otherwise, they will not be able to touch the type's stored properties to initialize them if those properties have the default isolation inferred. 2. All declarations inside actors and distributed actors do not participate in default isolation inference; they remain unspecified, so the existing isolation inference rules apply.
1 parent 6a3011d commit 2894896

File tree

4 files changed

+41
-34
lines changed

4 files changed

+41
-34
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5636,7 +5636,26 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
56365636
// within our module, make our default isolation main actor.
56375637
if (ctx.LangOpts.hasFeature(Feature::UnspecifiedMeansMainActorIsolated) &&
56385638
value->getModuleContext() == ctx.MainModule) {
5639-
defaultIsolation = ActorIsolation::forMainActor(ctx);
5639+
5640+
// Default global actor isolation does not apply to any declarations
5641+
// within actors and distributed actors.
5642+
bool inActorContext = false;
5643+
auto *dc = value->getInnermostDeclContext();
5644+
while (dc && !inActorContext) {
5645+
if (auto *nominal = dc->getSelfNominalTypeDecl()) {
5646+
inActorContext = nominal->isAnyActor();
5647+
}
5648+
dc = dc->getParent();
5649+
}
5650+
5651+
if (!inActorContext) {
5652+
// FIXME: deinit should be implicitly MainActor too.
5653+
if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5654+
isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5655+
isa<ConstructorDecl>(value)) {
5656+
defaultIsolation = ActorIsolation::forMainActor(ctx);
5657+
}
5658+
}
56405659
}
56415660

56425661
// If we have an async function... by default we inherit isolation.
@@ -5782,32 +5801,6 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
57825801
}
57835802
}
57845803

5785-
// If this is an actor, use the actor isolation of the actor.
5786-
if (ctx.LangOpts.hasFeature(Feature::UnspecifiedMeansMainActorIsolated)) {
5787-
// non-async inits and deinits need to be always nonisolated since we can
5788-
// run the deinit anywhere.
5789-
//
5790-
// TODO: We should add a check for if they are marked with global actor
5791-
// isolation.
5792-
if (auto *func = dyn_cast<AbstractFunctionDecl>(value)) {
5793-
if (isa<DestructorDecl>(func) && !func->isAsyncContext())
5794-
return {ActorIsolation::forNonisolated(false /*unsafe*/),
5795-
IsolationSource(func, IsolationSource::LexicalContext)};
5796-
5797-
if (isa<ConstructorDecl>(func) && !func->isAsyncContext())
5798-
return {ActorIsolation::forNonisolated(false /*unsafe*/),
5799-
IsolationSource(func, IsolationSource::LexicalContext)};
5800-
}
5801-
5802-
if (auto nominal = dyn_cast<NominalTypeDecl>(value)) {
5803-
if (nominal->isActor() && !nominal->isGlobalActor()) {
5804-
auto isolation = ActorIsolation::forActorInstanceSelf(value);
5805-
return {inferredIsolation(isolation),
5806-
IsolationSource(nominal, IsolationSource::LexicalContext)};
5807-
}
5808-
}
5809-
}
5810-
58115804
// If this is an accessor, use the actor isolation of its storage
58125805
// declaration.
58135806
if (auto accessor = dyn_cast<AccessorDecl>(value)) {

test/Concurrency/Runtime/unspecified_is_main_actor.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,17 @@ tests.test("checkIfOnMainQueue crashes off the main queue 2") { @CustomActor ()
7676
class Klass {}
7777

7878
struct MainActorIsolated {
79-
init() {}
79+
init() {
80+
checkIfOnMainQueue()
81+
}
8082

8183
func test() async {
8284
checkIfOnMainQueue()
8385
}
8486
};
8587

8688
tests.test("callNominalType") { @CustomActor () -> () in
87-
let x = MainActorIsolated()
89+
let x = await MainActorIsolated()
8890
// We would crash without hopping here.
8991
await x.test()
9092
}

test/Concurrency/assume_mainactor.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class Klass {
1111
// Implicit deinit
1212
// CHECK: // Klass.deinit
13-
// CHECK-NEXT: // Isolation: nonisolated
13+
// CHECK-NEXT: // Isolation: unspecified
1414
// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor5KlassCfd : $@convention(method) (@guaranteed Klass) -> @owned Builtin.NativeObject {
1515

1616
// Implicit deallocating deinit
@@ -163,7 +163,7 @@ nonisolated func nonisolatedFunctionTest() async {
163163

164164
actor MyActor {
165165
// CHECK: // variable initialization expression of MyActor.k
166-
// CHECK-NEXT: // Isolation: actor_instance
166+
// CHECK-NEXT: // Isolation: unspecified
167167
// CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor7MyActorC1kAA5KlassCvpfi : $@convention(thin) () -> @owned Klass {
168168

169169
// CHECK: // MyActor.k.getter
@@ -175,9 +175,21 @@ actor MyActor {
175175
// CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor7MyActorC1kAA5KlassCvs : $@convention(method) (@owned Klass, @sil_isolated @guaranteed MyActor) -> () {
176176
var k = Klass()
177177

178+
// CHECK: // static MyActor.f()
179+
// CHECK-NEXT: // Isolation: unspecified
180+
// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor7MyActorC1fyyFZ : $@convention(method) (@thick MyActor.Type) -> ()
181+
static func f() {}
182+
183+
struct Nested {
184+
// CHECK: // MyActor.Nested.f()
185+
// CHECK-NEXT: // Isolation: unspecified
186+
// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor7MyActorC6NestedV1fyyF : $@convention(method) (MyActor.Nested) -> ()
187+
func f() {}
188+
}
189+
178190
// Implicit deinit
179191
// CHECK: // MyActor.deinit
180-
// CHECK-NEXT: // Isolation: nonisolated
192+
// CHECK-NEXT: // Isolation: unspecified
181193
// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor7MyActorCfd : $@convention(method) (@guaranteed MyActor) -> @owned Builtin.NativeObject {
182194

183195
// Non-async init should be nonisolated

test/Concurrency/assume_mainactor_typechecker_errors.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func unspecifiedFunctionTest2() async {
5151
}
5252

5353
nonisolated func nonisolatedFunctionTest() async {
54-
let k = StructContainingKlass()
54+
let k = await StructContainingKlass()
5555
await unspecifiedAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}}
5656
await nonisolatedAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}}
5757
await mainActorAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}}
@@ -66,7 +66,7 @@ func testTask() async {
6666

6767
func testTaskDetached() async {
6868
Task.detached {
69-
let k = Klass(getDataFromSocket())
69+
let k = await Klass(getDataFromSocket())
7070
// Have to pop back onto the main thread to do something.
7171
await k.doSomething()
7272
}

0 commit comments

Comments
 (0)