Skip to content

Commit 2697773

Browse files
committed
[Concurrency] Only apply default main actor to local and nested
decls that are in a main actor isolated context. This prevents `@MainActor` from being inferred in a context where it cannot be used, while still allowing main actor code to be used in local contexts that are also main actor isolated. (cherry picked from commit 858e145)
1 parent a1a8d73 commit 2697773

File tree

2 files changed

+62
-14
lines changed

2 files changed

+62
-14
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6125,28 +6125,33 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
61256125
auto globalActorHelper = [&](Type globalActor)
61266126
-> std::optional<std::tuple<InferredActorIsolation, ValueDecl *,
61276127
std::optional<ActorIsolation>>> {
6128-
// Default global actor isolation does not apply to any declarations
6129-
// within actors and distributed actors, nor does it apply in a
6130-
// nonisolated type.
6128+
// Default main actor only applies to top-level declarations and
6129+
// in contexts that are also main actor isolated. It does not apply
6130+
// in {distributed} actor-isolated contexts nor in nonisolated
6131+
// contexts.
6132+
6133+
// Local declarations must check the isolation of their
6134+
// decl context.
6135+
if (value->getDeclContext()->isLocalContext()) {
6136+
auto contextIsolation =
6137+
getActorIsolationOfContext(value->getDeclContext());
6138+
if (!contextIsolation.isMainActor())
6139+
return {};
6140+
}
6141+
6142+
// Members and nested types must check the isolation of the enclosing
6143+
// nominal type.
61316144
auto *dc = value->getInnermostDeclContext();
61326145
while (dc) {
61336146
if (auto *nominal = dc->getSelfNominalTypeDecl()) {
61346147
if (nominal->isAnyActor())
61356148
return {};
61366149

61376150
if (dc != dyn_cast<DeclContext>(value)) {
6138-
switch (getActorIsolation(nominal)) {
6139-
case ActorIsolation::Unspecified:
6140-
case ActorIsolation::ActorInstance:
6141-
case ActorIsolation::Nonisolated:
6142-
case ActorIsolation::NonisolatedUnsafe:
6143-
case ActorIsolation::Erased:
6144-
case ActorIsolation::CallerIsolationInheriting:
6145-
return {};
6146-
6147-
case ActorIsolation::GlobalActor:
6151+
if (getActorIsolation(nominal).isMainActor())
61486152
break;
6149-
}
6153+
6154+
return {};
61506155
}
61516156
}
61526157
dc = dc->getParent();

test/Concurrency/assume_mainactor.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,46 @@ actor MyActor2 {
226226
// NonIsolated and not if print was inferred to be main actor.
227227
print("123")
228228
}
229+
230+
nonisolated func localDeclIsolation() async {
231+
struct Local {
232+
static func f() {}
233+
}
234+
235+
Local.f()
236+
237+
await withTaskGroup { group in
238+
group.addTask { }
239+
240+
await group.next()
241+
}
242+
}
243+
244+
@CustomActor
245+
class CustomActorIsolated {
246+
struct Nested {
247+
// CHECK: // static CustomActorIsolated.Nested.f()
248+
// CHECK-NEXT: // Isolation: unspecified
249+
static func f() {}
250+
}
251+
252+
// CHECK: // CustomActorIsolated.customIsolated()
253+
// CHECK-NEXT: // Isolation: global_actor. type: CustomActor
254+
func customIsolated() {
255+
Nested.f()
256+
}
257+
}
258+
259+
var global = 0
260+
261+
func onMain() {
262+
struct Nested {
263+
// CHECK: // static useGlobal() in Nested #1 in onMain()
264+
// CHECK-NEXT: // Isolation: global_actor. type: MainActor
265+
static func useGlobal() -> Int {
266+
global
267+
}
268+
}
269+
270+
_ = Nested.useGlobal()
271+
}

0 commit comments

Comments
 (0)