Skip to content

Commit 2c7fb6a

Browse files
committed
[NFC] Sema: Move determineClosureIsolation definition to the top level
Also combine the computed isolation and preconcurrency once at the end rather than at every return.
1 parent ba31190 commit 2c7fb6a

File tree

1 file changed

+74
-73
lines changed

1 file changed

+74
-73
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 74 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,7 +4642,7 @@ namespace {
46424642
}
46434643

46444644
// Attempt to resolve the global actor type of a closure.
4645-
Type resolveGlobalActorType(AbstractClosureExpr *ACE) {
4645+
Type resolveGlobalActorType(AbstractClosureExpr *ACE) const {
46464646
// Check whether the closure's type has a global actor already.
46474647
if (Type closureType = getType(ACE)) {
46484648
if (auto closureFnType = closureType->getAs<FunctionType>()) {
@@ -4664,91 +4664,92 @@ namespace {
46644664
///
46654665
/// This function assumes that enclosing closures have already had their
46664666
/// isolation checked.
4667-
ActorIsolation determineClosureIsolation(
4668-
AbstractClosureExpr *closure) {
4669-
bool preconcurrency = false;
4667+
ActorIsolation
4668+
determineClosureIsolation(AbstractClosureExpr *closure) const;
4669+
};
4670+
} // end anonymous namespace
46704671

4671-
if (auto explicitClosure = dyn_cast<ClosureExpr>(closure))
4672-
preconcurrency = explicitClosure->isIsolatedByPreconcurrency();
4672+
ActorIsolation ActorIsolationChecker::determineClosureIsolation(
4673+
AbstractClosureExpr *closure) const {
4674+
bool preconcurrency = false;
46734675

4674-
// If the closure specifies a global actor, use it.
4675-
if (Type globalActor = resolveGlobalActorType(closure)) {
4676-
return ActorIsolation::forGlobalActor(globalActor)
4677-
.withPreconcurrency(preconcurrency);
4678-
}
4676+
ActorIsolation isolation = [&] {
4677+
if (auto explicitClosure = dyn_cast<ClosureExpr>(closure))
4678+
preconcurrency = explicitClosure->isIsolatedByPreconcurrency();
46794679

4680-
if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure)) {
4681-
if (auto *attr =
4682-
explicitClosure->getAttrs().getAttribute<NonisolatedAttr>();
4683-
attr && ctx.LangOpts.hasFeature(Feature::ClosureIsolation)) {
4684-
return ActorIsolation::forNonisolated(attr->isUnsafe())
4685-
.withPreconcurrency(preconcurrency);
4686-
}
4680+
// If the closure specifies a global actor, use it.
4681+
if (Type globalActor = resolveGlobalActorType(closure)) {
4682+
return ActorIsolation::forGlobalActor(globalActor);
4683+
}
4684+
4685+
if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure)) {
4686+
if (auto *attr =
4687+
explicitClosure->getAttrs().getAttribute<NonisolatedAttr>();
4688+
attr && ctx.LangOpts.hasFeature(Feature::ClosureIsolation)) {
4689+
return ActorIsolation::forNonisolated(attr->isUnsafe());
46874690
}
4691+
}
46884692

4689-
// If a closure has an isolated parameter, it is isolated to that
4690-
// parameter.
4691-
for (auto param : *closure->getParameters()) {
4692-
if (param->isIsolated())
4693-
return ActorIsolation::forActorInstanceCapture(param)
4694-
.withPreconcurrency(preconcurrency);
4695-
}
4696-
4697-
// If we have a closure that acts as an isolation inference boundary, then
4698-
// we return that it is non-isolated.
4699-
//
4700-
// NOTE: Since we already checked for global actor isolated things, we
4701-
// know that all Sendable closures must be nonisolated. That is why it is
4702-
// safe to rely on this path to handle Sendable closures.
4703-
if (isIsolationInferenceBoundaryClosure(
4704-
closure, /*canInheritActorContext*/true))
4705-
return ActorIsolation::forNonisolated(/*unsafe=*/false)
4706-
.withPreconcurrency(preconcurrency);
4707-
4708-
// A non-Sendable closure gets its isolation from its context.
4709-
auto parentIsolation = getActorIsolationOfContext(
4710-
closure->getParent(), getClosureActorIsolation);
4711-
preconcurrency |= parentIsolation.preconcurrency();
4712-
4713-
// We must have parent isolation determined to get here.
4714-
switch (parentIsolation) {
4715-
case ActorIsolation::CallerIsolationInheriting:
4716-
case ActorIsolation::Nonisolated:
4717-
case ActorIsolation::NonisolatedUnsafe:
4718-
case ActorIsolation::Unspecified:
4719-
return ActorIsolation::forNonisolated(parentIsolation ==
4720-
ActorIsolation::NonisolatedUnsafe)
4721-
.withPreconcurrency(preconcurrency);
4693+
// If a closure has an isolated parameter, it is isolated to that
4694+
// parameter.
4695+
for (auto param : *closure->getParameters()) {
4696+
if (param->isIsolated())
4697+
return ActorIsolation::forActorInstanceCapture(param);
4698+
}
47224699

4723-
case ActorIsolation::Erased:
4724-
llvm_unreachable("context cannot have erased isolation");
4700+
// If we have a closure that acts as an isolation inference boundary, then
4701+
// we return that it is non-isolated.
4702+
//
4703+
// NOTE: Since we already checked for global actor isolated things, we
4704+
// know that all Sendable closures must be nonisolated. That is why it is
4705+
// safe to rely on this path to handle Sendable closures.
4706+
if (isIsolationInferenceBoundaryClosure(closure,
4707+
/*canInheritActorContext=*/true))
4708+
return ActorIsolation::forNonisolated(/*unsafe=*/false);
4709+
4710+
// A non-Sendable closure gets its isolation from its context.
4711+
auto parentIsolation = getActorIsolationOfContext(
4712+
closure->getParent(), getClosureActorIsolation);
4713+
preconcurrency |= parentIsolation.preconcurrency();
4714+
4715+
// We must have parent isolation determined to get here.
4716+
switch (parentIsolation) {
4717+
case ActorIsolation::CallerIsolationInheriting:
4718+
case ActorIsolation::Nonisolated:
4719+
case ActorIsolation::NonisolatedUnsafe:
4720+
case ActorIsolation::Unspecified:
4721+
return ActorIsolation::forNonisolated(
4722+
parentIsolation == ActorIsolation::NonisolatedUnsafe);
47254723

4726-
case ActorIsolation::GlobalActor: {
4727-
Type globalActor = closure->mapTypeIntoContext(
4728-
parentIsolation.getGlobalActor()->mapTypeOutOfContext());
4729-
return ActorIsolation::forGlobalActor(globalActor)
4730-
.withPreconcurrency(preconcurrency);
4731-
}
4724+
case ActorIsolation::Erased:
4725+
llvm_unreachable("context cannot have erased isolation");
47324726

4733-
case ActorIsolation::ActorInstance: {
4734-
if (checkIsolatedCapture) {
4735-
if (auto param = closure->getCaptureInfo().getIsolatedParamCapture())
4736-
return ActorIsolation::forActorInstanceCapture(param)
4737-
.withPreconcurrency(preconcurrency);
4738-
} else {
4739-
// If we don't have capture information during code completion, assume
4740-
// that the closure captures the `isolated` parameter from the parent
4741-
// context.
4742-
return parentIsolation;
4743-
}
4727+
case ActorIsolation::GlobalActor: {
4728+
Type globalActor = closure->mapTypeIntoContext(
4729+
parentIsolation.getGlobalActor()->mapTypeOutOfContext());
4730+
return ActorIsolation::forGlobalActor(globalActor);
4731+
}
47444732

4745-
return ActorIsolation::forNonisolated(/*unsafe=*/false)
4746-
.withPreconcurrency(preconcurrency);
4733+
case ActorIsolation::ActorInstance: {
4734+
if (checkIsolatedCapture) {
4735+
if (auto param = closure->getCaptureInfo().getIsolatedParamCapture())
4736+
return ActorIsolation::forActorInstanceCapture(param);
4737+
} else {
4738+
// If we don't have capture information during code completion, assume
4739+
// that the closure captures the `isolated` parameter from the parent
4740+
// context.
4741+
return parentIsolation;
47474742
}
4743+
4744+
return ActorIsolation::forNonisolated(/*unsafe=*/false);
47484745
}
47494746
}
4747+
}();
47504748

4751-
};
4749+
// Apply computed preconcurrency.
4750+
isolation = isolation.withPreconcurrency(preconcurrency);
4751+
4752+
return isolation;
47524753
}
47534754

47544755
bool ActorIsolationChecker::mayExecuteConcurrentlyWith(

0 commit comments

Comments
 (0)