Skip to content

Commit 121ed29

Browse files
committed
[concurrency] Split out the default inferred actor isolation computation into a helper from ActorIsolationRequest::evaluate.
This recommits commit 5d6131e with the reverting Concurrency rename removed.
1 parent dff88f9 commit 121ed29

File tree

1 file changed

+89
-74
lines changed

1 file changed

+89
-74
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 89 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -5523,6 +5523,83 @@ static void addAttributesForActorIsolation(ValueDecl *value,
55235523
}
55245524
}
55255525

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

5569-
if (FuncDecl *fd = dyn_cast<FuncDecl>(value)) {
5646+
if (auto *fd = dyn_cast<FuncDecl>(value)) {
55705647
// Main.main() and Main.$main are implicitly MainActor-protected.
55715648
// Any other isolation is an error.
55725649
std::optional<ActorIsolation> mainIsolation =
@@ -5599,74 +5676,11 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
55995676
IsolationSource(/*source*/ nullptr, IsolationSource::Explicit)};
56005677
}
56015678

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

56715685
// Function used when returning an inferred isolation.
56725686
auto inferredIsolation = [&](ActorIsolation inferred,
@@ -5677,16 +5691,17 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
56775691
// if the inferred isolation is not valid, then carry-over the overridden
56785692
// declaration's isolation as this decl's inferred isolation.
56795693
switch (validOverrideIsolation(value, inferred, overriddenValue,
5680-
*overriddenIso)) {
5694+
*overridenIsolation)) {
56815695
case OverrideIsolationResult::Allowed:
56825696
case OverrideIsolationResult::Sendable:
56835697
break;
56845698

56855699
case OverrideIsolationResult::Disallowed:
5686-
if (overriddenValue->hasClangNode() && overriddenIso->isUnspecified()) {
5687-
inferred = overriddenIso->withPreconcurrency(true);
5700+
if (overriddenValue->hasClangNode() &&
5701+
overridenIsolation->isUnspecified()) {
5702+
inferred = overridenIsolation->withPreconcurrency(true);
56885703
} else {
5689-
inferred = *overriddenIso;
5704+
inferred = *overridenIsolation;
56905705
}
56915706
break;
56925707
}
@@ -5944,7 +5959,7 @@ InferredActorIsolation ActorIsolationRequest::evaluate(
59445959
}
59455960

59465961
// Default isolation for this member.
5947-
return {defaultIsolation, defaultIsolationSource};
5962+
return defaultIsolation;
59485963
}
59495964

59505965
bool HasIsolatedSelfRequest::evaluate(

0 commit comments

Comments
 (0)