@@ -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
47544755bool ActorIsolationChecker::mayExecuteConcurrentlyWith (
0 commit comments