Skip to content

Commit 335d7e8

Browse files
authored
Merge pull request #83175 from hborla/local-decl-isolation-alt
[Concurrency] Only apply default main actor to local and nested decls that are in a main actor isolated context.
2 parents a390f02 + 7b0ba7b commit 335d7e8

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
@@ -6104,28 +6104,40 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
61046104
auto globalActorHelper = [&](Type globalActor)
61056105
-> std::optional<std::tuple<InferredActorIsolation, ValueDecl *,
61066106
std::optional<ActorIsolation>>> {
6107-
// Default global actor isolation does not apply to any declarations
6108-
// within actors and distributed actors, nor does it apply in a
6109-
// nonisolated type.
6107+
// Default main actor only applies to top-level declarations and
6108+
// in contexts that are also main actor isolated. It does not apply
6109+
// in {distributed} actor-isolated contexts nor in nonisolated
6110+
// contexts.
6111+
6112+
if (value->getDeclContext()->isLocalContext()) {
6113+
// Local storage is always nonisolated; region isolation computes
6114+
// whether the value is in an actor-isolated region based on
6115+
// the initializer expression.
6116+
auto *var = dyn_cast<VarDecl>(value);
6117+
if (var && var->hasStorage())
6118+
return {};
6119+
6120+
// Other local declarations must check the isolation of their
6121+
// decl context.
6122+
auto contextIsolation =
6123+
getActorIsolationOfContext(value->getDeclContext());
6124+
if (!contextIsolation.isMainActor())
6125+
return {};
6126+
}
6127+
6128+
// Members and nested types must check the isolation of the enclosing
6129+
// nominal type.
61106130
auto *dc = value->getInnermostDeclContext();
61116131
while (dc) {
61126132
if (auto *nominal = dc->getSelfNominalTypeDecl()) {
61136133
if (nominal->isAnyActor())
61146134
return {};
61156135

61166136
if (dc != dyn_cast<DeclContext>(value)) {
6117-
switch (getActorIsolation(nominal)) {
6118-
case ActorIsolation::Unspecified:
6119-
case ActorIsolation::ActorInstance:
6120-
case ActorIsolation::Nonisolated:
6121-
case ActorIsolation::NonisolatedUnsafe:
6122-
case ActorIsolation::Erased:
6123-
case ActorIsolation::CallerIsolationInheriting:
6124-
return {};
6125-
6126-
case ActorIsolation::GlobalActor:
6137+
if (getActorIsolation(nominal).isMainActor())
61276138
break;
6128-
}
6139+
6140+
return {};
61296141
}
61306142
}
61316143
dc = dc->getParent();

test/Concurrency/assume_mainactor.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,52 @@ struct S: P {
244244
}
245245
static let at = AT() // used to fail here
246246
}
247+
248+
nonisolated func localDeclIsolation() async {
249+
struct Local {
250+
static func f() {}
251+
}
252+
253+
Local.f()
254+
255+
await withTaskGroup { group in
256+
group.addTask { }
257+
258+
await group.next()
259+
}
260+
}
261+
262+
@CustomActor
263+
class CustomActorIsolated {
264+
struct Nested {
265+
// CHECK: // static CustomActorIsolated.Nested.f()
266+
// CHECK-NEXT: // Isolation: unspecified
267+
static func f() {}
268+
}
269+
270+
// CHECK: // CustomActorIsolated.customIsolated()
271+
// CHECK-NEXT: // Isolation: global_actor. type: CustomActor
272+
func customIsolated() {
273+
Nested.f()
274+
}
275+
}
276+
277+
var global = 0
278+
279+
func onMain() async {
280+
await withTaskGroup { group in
281+
group.addTask { }
282+
283+
await group.next()
284+
}
285+
286+
struct Nested {
287+
// CHECK: // static useGlobal() in Nested #1 in onMain()
288+
// CHECK-NEXT: // Isolation: global_actor. type: MainActor
289+
static func useGlobal() -> Int {
290+
global
291+
}
292+
}
293+
294+
_ = Nested.useGlobal()
295+
}

0 commit comments

Comments
 (0)