@@ -7851,18 +7851,6 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7851
7851
return ctorCall;
7852
7852
}
7853
7853
7854
- // / Determine whether this closure should be treated as Sendable.
7855
- static bool isSendableClosure (ConstraintSystem &cs,
7856
- const AbstractClosureExpr *closure) {
7857
- if (auto fnType = cs.getType (const_cast <AbstractClosureExpr *>(closure))
7858
- ->getAs <FunctionType>()) {
7859
- if (fnType->isSendable ())
7860
- return true ;
7861
- }
7862
-
7863
- return false ;
7864
- }
7865
-
7866
7854
bool ExprRewriter::isDistributedThunk (ConcreteDeclRef ref, Expr *context) {
7867
7855
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl ());
7868
7856
if (!(FD && FD->isInstanceMember () && FD->isDistributed ()))
@@ -7886,55 +7874,60 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
7886
7874
7887
7875
// If this is a method reference on an potentially isolated
7888
7876
// actor then it cannot be a remote thunk.
7889
- if (isPotentiallyIsolatedActor (actor, [&](ParamDecl *P) {
7890
- return P->isIsolated () ||
7891
- llvm::is_contained (solution.isolatedParams , P);
7892
- }))
7893
- return false ;
7894
-
7895
- if (actor->isKnownToBeLocal ())
7896
- return false ;
7897
-
7898
- bool isInAsyncLetInitializer = target && target->isAsyncLetInitializer ();
7899
-
7900
- auto isActorInitOrDeInitContext = [&](const DeclContext *dc) {
7901
- return ::isActorInitOrDeInitContext (
7902
- dc, [&](const AbstractClosureExpr *closure) {
7903
- return isSendableClosure (cs, closure);
7904
- });
7905
- };
7906
-
7907
- switch (ActorIsolationRestriction::forDeclaration (ref, dc)) {
7908
- case ActorIsolationRestriction::CrossActorSelf: {
7909
- // Not a thunk if it's used in actor init or de-init.
7910
- if (!isInAsyncLetInitializer && isActorInitOrDeInitContext (dc))
7911
- return false ;
7877
+ bool isPotentiallyIsolated = isPotentiallyIsolatedActor (
7878
+ actor,
7879
+ [&](ParamDecl *P) {
7880
+ return P->isIsolated () ||
7881
+ llvm::is_contained (solution.isolatedParams , P);
7882
+ });
7883
+
7884
+ // Adjust the declaration context to the innermost context that is neither
7885
+ // a local function nor a closure, so that the actor reference is checked
7886
+ auto referenceDC = dc;
7887
+ while (true ) {
7888
+ switch (referenceDC->getContextKind ()) {
7889
+ case DeclContextKind::AbstractClosureExpr:
7890
+ case DeclContextKind::Initializer:
7891
+ case DeclContextKind::SerializedLocal:
7892
+ referenceDC = referenceDC->getParent ();
7893
+ continue ;
7912
7894
7913
- // Here we know that the method could be used across actors
7914
- // and the actor it's used on is non-isolated, which means
7915
- // that it could be a thunk, so we have to be conservative
7916
- // about it.
7917
- return true ;
7918
- }
7895
+ case DeclContextKind::AbstractFunctionDecl:
7896
+ case DeclContextKind::GenericTypeDecl:
7897
+ case DeclContextKind::SubscriptDecl:
7898
+ if (auto value = dyn_cast<ValueDecl>(referenceDC->getAsDecl ())) {
7899
+ if (value->isLocalCapture ()) {
7900
+ referenceDC = referenceDC->getParent ();
7901
+ continue ;
7902
+ }
7903
+ }
7904
+ break ;
7919
7905
7920
- case ActorIsolationRestriction::ActorSelf: {
7921
- // An instance member of an actor can be referenced from an actor's
7922
- // designated initializer or deinitializer.
7923
- if (actor->isActorSelf () && !isInAsyncLetInitializer) {
7924
- if (auto *fn = isActorInitOrDeInitContext (dc)) {
7925
- if (!(isa<ConstructorDecl>(fn) &&
7926
- cast<ConstructorDecl>(fn)->isConvenienceInit ()))
7927
- return false ;
7928
- }
7906
+ case DeclContextKind::EnumElementDecl:
7907
+ case DeclContextKind::ExtensionDecl:
7908
+ case DeclContextKind::FileUnit:
7909
+ case DeclContextKind::Module:
7910
+ case DeclContextKind::TopLevelCodeDecl:
7911
+ break ;
7929
7912
}
7930
7913
7931
- // Call on a non-isolated actor in async context requires
7932
- // implicit thunk.
7933
- return isInAsyncLetInitializer || cs.isAsynchronousContext (dc);
7914
+ break ;
7934
7915
}
7935
7916
7936
- default :
7917
+ // Create a simple actor reference, assuming that we might be in a
7918
+ // non-isolated context but knowing whether it's potentially isolated.
7919
+ // We only care about the "distributed" flag.
7920
+ ReferencedActor actorRef = ReferencedActor (
7921
+ actor, isPotentiallyIsolated, ReferencedActor::NonIsolatedContext);
7922
+ auto refResult = ActorReferenceResult::forReference (
7923
+ ref, context->getLoc (), referenceDC, None, actorRef);
7924
+ switch (refResult) {
7925
+ case ActorReferenceResult::ExitsActorToNonisolated:
7926
+ case ActorReferenceResult::SameConcurrencyDomain:
7937
7927
return false ;
7928
+
7929
+ case ActorReferenceResult::EntersActor:
7930
+ return refResult.options .contains (ActorReferenceResult::Flags::Distributed);
7938
7931
}
7939
7932
}
7940
7933
0 commit comments