@@ -698,27 +698,6 @@ static bool isAsyncCall(
698698// / features.
699699static bool shouldDiagnoseExistingDataRaces (const DeclContext *dc);
700700
701- // / Determine whether this closure should be treated as Sendable.
702- // /
703- // / \param forActorIsolation Whether this check is for the purposes of
704- // / determining whether the closure must be non-isolated.
705- static bool isSendableClosure (
706- const AbstractClosureExpr *closure, bool forActorIsolation) {
707- if (auto explicitClosure = dyn_cast<ClosureExpr>(closure)) {
708- if (forActorIsolation && explicitClosure->inheritsActorContext ()) {
709- return false ;
710- }
711- }
712-
713- if (auto type = closure->getType ()) {
714- if (auto fnType = type->getAs <AnyFunctionType>())
715- if (fnType->isSendable ())
716- return true ;
717- }
718-
719- return false ;
720- }
721-
722701// / Returns true if this closure acts as an inference boundary in the AST. An
723702// / inference boundary is an expression in the AST where we newly infer
724703// / isolation different from our parent decl context.
@@ -733,30 +712,23 @@ static bool isSendableClosure(
733712// / function. That @MainActor closure would act as an Isolation Inference
734713// / Boundary.
735714// /
736- // / \arg forActorIsolation we currently have two slightly varying semantics
737- // / here. If this is set, then we assuming that we are being called recursively
738- // / while walking up a decl context path to determine the actor isolation of a
739- // / closure. In such a case, we do not want to be a boundary if we should
740- // / inheritActorContext. In other contexts though, we want to determine if the
741- // / closure is part of an init or deinit. In such a case, we are walking up the
742- // / decl context chain and we want to stop if we see a sending parameter since
743- // / in such a case, the sending closure parameter is known to not be part of the
744- // / init or deinit.
715+ // / \param canInheritActorContext Whether or not the closure is allowed to
716+ // / inherit the isolation of the enclosing context. If this is \c true ,
717+ // / the closure is not considered an isolation inference boundary if the
718+ // / \c @_inheritActorContext attribute is applied to the closure. This
719+ // / attribute is inferred from a parameter declaration for closure arguments,
720+ // / and it's set on the closure in CSApply.
745721static bool
746722isIsolationInferenceBoundaryClosure (const AbstractClosureExpr *closure,
747- bool forActorIsolation ) {
723+ bool canInheritActorContext ) {
748724 if (auto *ce = dyn_cast<ClosureExpr>(closure)) {
749- if (!forActorIsolation) {
750- // For example, one would along this path see if for flow sensitive
751- // isolation the closure is part of an init or deinit.
752- if (ce->isPassedToSendingParameter ())
753- return true ;
754- } else {
755- // This is for actor isolation. If we have inheritActorContext though, we
756- // do not want to do anything since we are part of our parent's isolation.
757- if (!ce->inheritsActorContext () && ce->isPassedToSendingParameter ())
758- return true ;
759- }
725+ // If the closure can inherit the isolation of the enclosing context,
726+ // it is not an actor isolation inference boundary.
727+ if (canInheritActorContext && ce->inheritsActorContext ())
728+ return false ;
729+
730+ if (ce->isPassedToSendingParameter ())
731+ return true ;
760732 }
761733
762734 // An autoclosure for an async let acts as a boundary. It is non-Sendable
@@ -766,7 +738,7 @@ isIsolationInferenceBoundaryClosure(const AbstractClosureExpr *closure,
766738 return true ;
767739 }
768740
769- return isSendableClosure ( closure, forActorIsolation );
741+ return closure-> isSendable ( );
770742}
771743
772744// / Add Fix-It text for the given nominal type to adopt Sendable.
@@ -1693,7 +1665,7 @@ swift::isActorInitOrDeInitContext(const DeclContext *dc) {
16931665 // Stop looking if we hit an isolation inference boundary.
16941666 if (auto *closure = dyn_cast<AbstractClosureExpr>(dc)) {
16951667 if (isIsolationInferenceBoundaryClosure (closure,
1696- false /* is for actor isolation */ ))
1668+ /* canInheritActorContext */ false ))
16971669 return nullptr ;
16981670
16991671 // Otherwise, look through our closure at the closure's parent decl
@@ -2704,7 +2676,7 @@ namespace {
27042676 // because they cannot leave the isolation domain they're created
27052677 // in anyway.
27062678 if (isIsolationInferenceBoundaryClosure (
2707- closure, /* can inherit actor context */ false ))
2679+ closure, /* canInheritActorContext */ false ))
27082680 return false ;
27092681
27102682 if (closure->getActorIsolation ().isActorIsolated ())
@@ -3238,7 +3210,7 @@ namespace {
32383210 case ActorIsolation::Unspecified:
32393211 case ActorIsolation::Nonisolated:
32403212 case ActorIsolation::NonisolatedUnsafe:
3241- if (isSendableClosure ( closure, /* forActorIsolation= */ true )) {
3213+ if (closure-> isSendable ( )) {
32423214 return ReferencedActor (var, isPotentiallyIsolated, ReferencedActor::SendableClosure);
32433215 }
32443216
@@ -4516,7 +4488,7 @@ namespace {
45164488 // know that all Sendable closures must be nonisolated. That is why it is
45174489 // safe to rely on this path to handle Sendable closures.
45184490 if (isIsolationInferenceBoundaryClosure (
4519- closure, true /* is for closure isolation */ ))
4491+ closure, /* canInheritActorContext */ true ))
45204492 return ActorIsolation::forNonisolated (/* unsafe=*/ false )
45214493 .withPreconcurrency (preconcurrency);
45224494
@@ -4607,7 +4579,7 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
46074579 while (useContext != defContext) {
46084580 // If we find a concurrent closure... it can be run concurrently.
46094581 if (auto closure = dyn_cast<AbstractClosureExpr>(useContext)) {
4610- if (isSendableClosure ( closure, /* forActorIsolation= */ false ))
4582+ if (closure-> isSendable ( ))
46114583 return true ;
46124584
46134585 if (isolatedStateMayEscape)
0 commit comments