Skip to content

Commit c846306

Browse files
authored
Merge pull request #79145 from gottesmm/pr-4f8d798bbab9e98210dd45e18e92720f7c73cc7d
[concurrency] Split out the default inferred actor isolation computation into a helper from ActorIsolationRequest::evaluate.
2 parents eb48925 + 5d6131e commit c846306

File tree

1 file changed

+88
-74
lines changed

1 file changed

+88
-74
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 88 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -5533,6 +5533,82 @@ static void addAttributesForActorIsolation(ValueDecl *value,
55335533
}
55345534
}
55355535

5536+
/// Determine the default isolation and isolation source for this declaration,
5537+
/// which may still be overridden by other inference rules.
5538+
static std::tuple<InferredActorIsolation, ValueDecl *,
5539+
std::optional<ActorIsolation>>
5540+
computeDefaultInferredActorIsolation(ValueDecl *value) {
5541+
auto &ctx = value->getASTContext();
5542+
5543+
// If we are supposed to infer main actor isolation by default for entities
5544+
// within our module, make our default isolation main actor.
5545+
if (ctx.LangOpts.hasFeature(Feature::UnspecifiedMeansMainActorIsolated) &&
5546+
value->getModuleContext() == ctx.MainModule) {
5547+
5548+
// Default global actor isolation does not apply to any declarations
5549+
// within actors and distributed actors.
5550+
bool inActorContext = false;
5551+
auto *dc = value->getInnermostDeclContext();
5552+
while (dc && !inActorContext) {
5553+
if (auto *nominal = dc->getSelfNominalTypeDecl()) {
5554+
inActorContext = nominal->isAnyActor();
5555+
}
5556+
dc = dc->getParent();
5557+
}
5558+
5559+
if (!inActorContext) {
5560+
// FIXME: deinit should be implicitly MainActor too.
5561+
if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5562+
isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5563+
isa<ConstructorDecl>(value)) {
5564+
return {{ActorIsolation::forMainActor(ctx), {}}, nullptr, {}};
5565+
}
5566+
}
5567+
}
5568+
5569+
// If we have an async function... by default we inherit isolation.
5570+
if (ctx.LangOpts.hasFeature(
5571+
Feature::NonIsolatedAsyncInheritsIsolationFromContext)) {
5572+
if (auto *func = dyn_cast<AbstractFunctionDecl>(value);
5573+
func && func->hasAsync() &&
5574+
func->getModuleContext() == ctx.MainModule) {
5575+
return {{ActorIsolation::forNonisolated(false /*is unsafe*/), {}},
5576+
nullptr,
5577+
{}};
5578+
}
5579+
}
5580+
5581+
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
5582+
// A @Sendable function is assumed to be actor-independent.
5583+
if (func->isSendable()) {
5584+
return {
5585+
{ActorIsolation::forConcurrent(/*unsafe=*/false), {}}, nullptr, {}};
5586+
}
5587+
}
5588+
5589+
// When no other isolation applies, an actor's non-async init is independent
5590+
if (auto nominal = value->getDeclContext()->getSelfNominalTypeDecl())
5591+
if (nominal->isAnyActor())
5592+
if (auto ctor = dyn_cast<ConstructorDecl>(value))
5593+
if (!ctor->hasAsync())
5594+
return {{ActorIsolation::forConcurrent(/*unsafe=*/false), {}},
5595+
nullptr,
5596+
{}};
5597+
5598+
// Look for and remember the overridden declaration's isolation.
5599+
if (auto *overriddenValue = value->getOverriddenDeclOrSuperDeinit()) {
5600+
// Use the overridden decl's iso as the default isolation for this decl.
5601+
auto isolation = getOverriddenIsolationFor(value);
5602+
return {{isolation,
5603+
IsolationSource(overriddenValue, IsolationSource::Override)},
5604+
overriddenValue,
5605+
isolation};
5606+
}
5607+
5608+
// We did not find anything special, return unspecified.
5609+
return {{ActorIsolation::forUnspecified(), {}}, nullptr, {}};
5610+
}
5611+
55365612
InferredActorIsolation ActorIsolationRequest::evaluate(
55375613
Evaluator &evaluator, ValueDecl *value) const {
55385614
// If this declaration has actor-isolated "self", it's isolated to that
@@ -5576,7 +5652,7 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
55765652
value->getAttrs().add(preconcurrency);
55775653
}
55785654

5579-
if (FuncDecl *fd = dyn_cast<FuncDecl>(value)) {
5655+
if (auto *fd = dyn_cast<FuncDecl>(value)) {
55805656
// Main.main() and Main.$main are implicitly MainActor-protected.
55815657
// Any other isolation is an error.
55825658
std::optional<ActorIsolation> mainIsolation =
@@ -5609,74 +5685,11 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
56095685
IsolationSource(/*source*/ nullptr, IsolationSource::Explicit)};
56105686
}
56115687

5612-
// Determine the default isolation for this declaration, which may still be
5613-
// overridden by other inference rules.
5614-
ActorIsolation defaultIsolation = ActorIsolation::forUnspecified();
5615-
IsolationSource defaultIsolationSource;
5616-
5617-
// If we are supposed to infer main actor isolation by default for entities
5618-
// within our module, make our default isolation main actor.
5619-
if (ctx.LangOpts.hasFeature(Feature::UnspecifiedMeansMainActorIsolated) &&
5620-
value->getModuleContext() == ctx.MainModule) {
5621-
5622-
// Default global actor isolation does not apply to any declarations
5623-
// within actors and distributed actors.
5624-
bool inActorContext = false;
5625-
auto *dc = value->getInnermostDeclContext();
5626-
while (dc && !inActorContext) {
5627-
if (auto *nominal = dc->getSelfNominalTypeDecl()) {
5628-
inActorContext = nominal->isAnyActor();
5629-
}
5630-
dc = dc->getParent();
5631-
}
5632-
5633-
if (!inActorContext) {
5634-
// FIXME: deinit should be implicitly MainActor too.
5635-
if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
5636-
isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
5637-
isa<ConstructorDecl>(value)) {
5638-
defaultIsolation = ActorIsolation::forMainActor(ctx);
5639-
}
5640-
}
5641-
}
5642-
5643-
// If we have an async function... by default we inherit isolation.
5644-
if (ctx.LangOpts.hasFeature(
5645-
Feature::NonIsolatedAsyncInheritsIsolationFromContext)) {
5646-
if (auto *func = dyn_cast<AbstractFunctionDecl>(value);
5647-
func && func->hasAsync() &&
5648-
func->getModuleContext() == ctx.MainModule) {
5649-
defaultIsolation = ActorIsolation::forNonisolated(false /*is unsafe*/);
5650-
}
5651-
}
5652-
5653-
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
5654-
// A @Sendable function is assumed to be actor-independent.
5655-
if (func->isSendable()) {
5656-
defaultIsolation = ActorIsolation::forConcurrent(/*unsafe=*/false);
5657-
}
5658-
}
5659-
5660-
// When no other isolation applies, an actor's non-async init is independent
5661-
if (auto nominal = value->getDeclContext()->getSelfNominalTypeDecl())
5662-
if (nominal->isAnyActor())
5663-
if (auto ctor = dyn_cast<ConstructorDecl>(value))
5664-
if (!ctor->hasAsync())
5665-
defaultIsolation = ActorIsolation::forConcurrent(/*unsafe=*/false);
5666-
5667-
// Look for and remember the overridden declaration's isolation.
5668-
std::optional<ActorIsolation> overriddenIso;
5669-
ValueDecl *overriddenValue = value->getOverriddenDeclOrSuperDeinit();
5670-
if (overriddenValue) {
5671-
// use the overridden decl's iso as the default isolation for this decl.
5672-
defaultIsolation = getOverriddenIsolationFor(value);
5673-
defaultIsolationSource =
5674-
IsolationSource(overriddenValue, IsolationSource::Override);
5675-
overriddenIso = defaultIsolation;
5676-
}
5677-
5678-
// NOTE: After this point, the default has been set. Only touch the default
5679-
// isolation above this point since code below assumes it is now constant.
5688+
InferredActorIsolation defaultIsolation;
5689+
ValueDecl *overriddenValue;
5690+
std::optional<ActorIsolation> overriddenIsolation;
5691+
std::tie(defaultIsolation, overriddenValue, overriddenIsolation) =
5692+
computeDefaultInferredActorIsolation(value);
56805693

56815694
// Function used when returning an inferred isolation.
56825695
auto inferredIsolation = [&](ActorIsolation inferred,
@@ -5687,16 +5700,17 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
56875700
// if the inferred isolation is not valid, then carry-over the overridden
56885701
// declaration's isolation as this decl's inferred isolation.
56895702
switch (validOverrideIsolation(value, inferred, overriddenValue,
5690-
*overriddenIso)) {
5703+
*overriddenIsolation)) {
56915704
case OverrideIsolationResult::Allowed:
56925705
case OverrideIsolationResult::Sendable:
56935706
break;
56945707

56955708
case OverrideIsolationResult::Disallowed:
5696-
if (overriddenValue->hasClangNode() && overriddenIso->isUnspecified()) {
5697-
inferred = overriddenIso->withPreconcurrency(true);
5709+
if (overriddenValue->hasClangNode() &&
5710+
overriddenIsolation->isUnspecified()) {
5711+
inferred = overriddenIsolation->withPreconcurrency(true);
56985712
} else {
5699-
inferred = *overriddenIso;
5713+
inferred = *overriddenIsolation;
57005714
}
57015715
break;
57025716
}
@@ -5955,7 +5969,7 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
59555969
}
59565970

59575971
// Default isolation for this member.
5958-
return {defaultIsolation, defaultIsolationSource};
5972+
return defaultIsolation;
59595973
}
59605974

59615975
bool HasIsolatedSelfRequest::evaluate(

0 commit comments

Comments
 (0)