@@ -7786,18 +7786,6 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7786
7786
return ctorCall;
7787
7787
}
7788
7788
7789
- // / Determine whether this closure should be treated as Sendable.
7790
- static bool isSendableClosure (ConstraintSystem &cs,
7791
- const AbstractClosureExpr *closure) {
7792
- if (auto fnType = cs.getType (const_cast <AbstractClosureExpr *>(closure))
7793
- ->getAs <FunctionType>()) {
7794
- if (fnType->isSendable ())
7795
- return true ;
7796
- }
7797
-
7798
- return false ;
7799
- }
7800
-
7801
7789
bool ExprRewriter::isDistributedThunk (ConcreteDeclRef ref, Expr *context) {
7802
7790
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl ());
7803
7791
if (!(FD && FD->isInstanceMember () && FD->isDistributed ()))
@@ -7821,55 +7809,60 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
7821
7809
7822
7810
// If this is a method reference on an potentially isolated
7823
7811
// actor then it cannot be a remote thunk.
7824
- if (isPotentiallyIsolatedActor (actor, [&](ParamDecl *P) {
7825
- return P->isIsolated () ||
7826
- llvm::is_contained (solution.isolatedParams , P);
7827
- }))
7828
- return false ;
7829
-
7830
- if (actor->isKnownToBeLocal ())
7831
- return false ;
7832
-
7833
- bool isInAsyncLetInitializer = target && target->isAsyncLetInitializer ();
7834
-
7835
- auto isActorInitOrDeInitContext = [&](const DeclContext *dc) {
7836
- return ::isActorInitOrDeInitContext (
7837
- dc, [&](const AbstractClosureExpr *closure) {
7838
- return isSendableClosure (cs, closure);
7839
- });
7840
- };
7841
-
7842
- switch (ActorIsolationRestriction::forDeclaration (ref, dc)) {
7843
- case ActorIsolationRestriction::CrossActorSelf: {
7844
- // Not a thunk if it's used in actor init or de-init.
7845
- if (!isInAsyncLetInitializer && isActorInitOrDeInitContext (dc))
7846
- return false ;
7812
+ bool isPotentiallyIsolated = isPotentiallyIsolatedActor (
7813
+ actor,
7814
+ [&](ParamDecl *P) {
7815
+ return P->isIsolated () ||
7816
+ llvm::is_contained (solution.isolatedParams , P);
7817
+ });
7818
+
7819
+ // Adjust the declaration context to the innermost context that is neither
7820
+ // a local function nor a closure, so that the actor reference is checked
7821
+ auto referenceDC = dc;
7822
+ while (true ) {
7823
+ switch (referenceDC->getContextKind ()) {
7824
+ case DeclContextKind::AbstractClosureExpr:
7825
+ case DeclContextKind::Initializer:
7826
+ case DeclContextKind::SerializedLocal:
7827
+ referenceDC = referenceDC->getParent ();
7828
+ continue ;
7847
7829
7848
- // Here we know that the method could be used across actors
7849
- // and the actor it's used on is non-isolated, which means
7850
- // that it could be a thunk, so we have to be conservative
7851
- // about it.
7852
- return true ;
7853
- }
7830
+ case DeclContextKind::AbstractFunctionDecl:
7831
+ case DeclContextKind::GenericTypeDecl:
7832
+ case DeclContextKind::SubscriptDecl:
7833
+ if (auto value = dyn_cast<ValueDecl>(referenceDC->getAsDecl ())) {
7834
+ if (value->isLocalCapture ()) {
7835
+ referenceDC = referenceDC->getParent ();
7836
+ continue ;
7837
+ }
7838
+ }
7839
+ break ;
7854
7840
7855
- case ActorIsolationRestriction::ActorSelf: {
7856
- // An instance member of an actor can be referenced from an actor's
7857
- // designated initializer or deinitializer.
7858
- if (actor->isActorSelf () && !isInAsyncLetInitializer) {
7859
- if (auto *fn = isActorInitOrDeInitContext (dc)) {
7860
- if (!(isa<ConstructorDecl>(fn) &&
7861
- cast<ConstructorDecl>(fn)->isConvenienceInit ()))
7862
- return false ;
7863
- }
7841
+ case DeclContextKind::EnumElementDecl:
7842
+ case DeclContextKind::ExtensionDecl:
7843
+ case DeclContextKind::FileUnit:
7844
+ case DeclContextKind::Module:
7845
+ case DeclContextKind::TopLevelCodeDecl:
7846
+ break ;
7864
7847
}
7865
7848
7866
- // Call on a non-isolated actor in async context requires
7867
- // implicit thunk.
7868
- return isInAsyncLetInitializer || cs.isAsynchronousContext (dc);
7849
+ break ;
7869
7850
}
7870
7851
7871
- default :
7852
+ // Create a simple actor reference, assuming that we might be in a
7853
+ // non-isolated context but knowing whether it's potentially isolated.
7854
+ // We only care about the "distributed" flag.
7855
+ ReferencedActor actorRef = ReferencedActor (
7856
+ actor, isPotentiallyIsolated, ReferencedActor::NonIsolatedContext);
7857
+ auto refResult = ActorReferenceResult::forReference (
7858
+ ref, context->getLoc (), referenceDC, None, actorRef);
7859
+ switch (refResult) {
7860
+ case ActorReferenceResult::ExitsActorToNonisolated:
7861
+ case ActorReferenceResult::SameConcurrencyDomain:
7872
7862
return false ;
7863
+
7864
+ case ActorReferenceResult::EntersActor:
7865
+ return refResult.options .contains (ActorReferenceResult::Flags::Distributed);
7873
7866
}
7874
7867
}
7875
7868
0 commit comments