Skip to content

Commit 4518bc9

Browse files
authored
Merge pull request #83254 from hborla/6.2-local-decl-isolation-alt
[6.2][Concurrency] Only apply default main actor to local and nested decls that are in a main actor isolated context.
2 parents ef4a51e + 276e5de commit 4518bc9

File tree

2 files changed

+75
-14
lines changed

2 files changed

+75
-14
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6125,28 +6125,40 @@ 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+
if (value->getDeclContext()->isLocalContext()) {
6134+
// Local storage is always nonisolated; region isolation computes
6135+
// whether the value is in an actor-isolated region based on
6136+
// the initializer expression.
6137+
auto *var = dyn_cast<VarDecl>(value);
6138+
if (var && var->hasStorage())
6139+
return {};
6140+
6141+
// Other local declarations must check the isolation of their
6142+
// decl context.
6143+
auto contextIsolation =
6144+
getActorIsolationOfContext(value->getDeclContext());
6145+
if (!contextIsolation.isMainActor())
6146+
return {};
6147+
}
6148+
6149+
// Members and nested types must check the isolation of the enclosing
6150+
// nominal type.
61316151
auto *dc = value->getInnermostDeclContext();
61326152
while (dc) {
61336153
if (auto *nominal = dc->getSelfNominalTypeDecl()) {
61346154
if (nominal->isAnyActor())
61356155
return {};
61366156

61376157
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:
6158+
if (getActorIsolation(nominal).isMainActor())
61486159
break;
6149-
}
6160+
6161+
return {};
61506162
}
61516163
}
61526164
dc = dc->getParent();

test/Concurrency/assume_mainactor.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,52 @@ 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() async {
262+
await withTaskGroup { group in
263+
group.addTask { }
264+
265+
await group.next()
266+
}
267+
268+
struct Nested {
269+
// CHECK: // static useGlobal() in Nested #1 in onMain()
270+
// CHECK-NEXT: // Isolation: global_actor. type: MainActor
271+
static func useGlobal() -> Int {
272+
global
273+
}
274+
}
275+
276+
_ = Nested.useGlobal()
277+
}

0 commit comments

Comments
 (0)