Skip to content

Commit 4c77d71

Browse files
committed
Reseat the "is distributed thunk" check onto actor reference checking.
Rather than write an appoximation of the "is distributed thunk" check within the type checker, use the new actor reference checking logic with a referenced actor that is synthesized from the information in the constraint system.
1 parent 58382a8 commit 4c77d71

File tree

1 file changed

+47
-54
lines changed

1 file changed

+47
-54
lines changed

lib/Sema/CSApply.cpp

Lines changed: 47 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7786,18 +7786,6 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
77867786
return ctorCall;
77877787
}
77887788

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-
78017789
bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
78027790
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl());
78037791
if (!(FD && FD->isInstanceMember() && FD->isDistributed()))
@@ -7821,55 +7809,60 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
78217809

78227810
// If this is a method reference on an potentially isolated
78237811
// 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;
78477829

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;
78547840

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;
78647847
}
78657848

7866-
// Call on a non-isolated actor in async context requires
7867-
// implicit thunk.
7868-
return isInAsyncLetInitializer || cs.isAsynchronousContext(dc);
7849+
break;
78697850
}
78707851

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:
78727862
return false;
7863+
7864+
case ActorReferenceResult::EntersActor:
7865+
return refResult.options.contains(ActorReferenceResult::Flags::Distributed);
78737866
}
78747867
}
78757868

0 commit comments

Comments
 (0)