Skip to content

Commit 00cae5a

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. (cherry picked from commit 4c77d71)
1 parent 863fdf9 commit 00cae5a

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
@@ -7851,18 +7851,6 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
78517851
return ctorCall;
78527852
}
78537853

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-
78667854
bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
78677855
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(ref.getDecl());
78687856
if (!(FD && FD->isInstanceMember() && FD->isDistributed()))
@@ -7886,55 +7874,60 @@ bool ExprRewriter::isDistributedThunk(ConcreteDeclRef ref, Expr *context) {
78867874

78877875
// If this is a method reference on an potentially isolated
78887876
// 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;
79127894

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

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;
79297912
}
79307913

7931-
// Call on a non-isolated actor in async context requires
7932-
// implicit thunk.
7933-
return isInAsyncLetInitializer || cs.isAsynchronousContext(dc);
7914+
break;
79347915
}
79357916

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:
79377927
return false;
7928+
7929+
case ActorReferenceResult::EntersActor:
7930+
return refResult.options.contains(ActorReferenceResult::Flags::Distributed);
79387931
}
79397932
}
79407933

0 commit comments

Comments
 (0)